Skip to content

Commit

Permalink
图片在Typora里面无法查看,修改图片的相对路径
Browse files Browse the repository at this point in the history
  • Loading branch information
zhujinming committed May 7, 2020
1 parent 141ecfd commit 068196e
Show file tree
Hide file tree
Showing 57 changed files with 232 additions and 231 deletions.
2 changes: 1 addition & 1 deletion docs/Dubbo/SPI/Dubbo与Java的SPI机制.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ dubbo自己实现了一套SPI机制,并对 JDK的SPI进行了改进。

下面我们看一下Dubbo 的 SPI扩展机制实现的结构目录。

![avatar](/images/Dubbo/SPI组件目录结构.png)
![avatar](../../../images/Dubbo/SPI组件目录结构.png)

### SPI 注解
首先看一下 SPI注解。在某个接口上加上 @SPI 注解后,表明该接口为可扩展接口。比如,协议扩展接口Protocol,如果使用者在 <dubbo:protocol />、<dubbo:service />、<dubbo:reference /> 都没有指定 protocol属性 的话,那么就默认使用 DubboProtocol 作为接口Protocol的实现,因为在 Protocol 上有 @SPI("dubbo")注解。而这个 protocol属性值 或者默认值会被当作该接口的实现类中的一个key,dubbo 会去 META-INF.dubbo.internal下的com.alibaba.dubbo.rpc.Protocol文件中找该key对应的value,源码如下。
Expand Down
4 changes: 2 additions & 2 deletions docs/Dubbo/architectureDesign/Dubbo整体架构.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
## 项目结构
首先从GitHub 上 down下来Dubbo项目,我们根据里面的目录名 也能大概猜出来各个模块的作用。

![avatar](/images/Dubbo/dubbo项目结构.png)
![avatar](../../../images/Dubbo/dubbo项目结构.png)

### dubbo-­common
公共逻辑模块,定义了各模块中 通用的 组件 和 工具类,如:IO、日志、配置处理等。
Expand Down Expand Up @@ -34,7 +34,7 @@ dubbo配置模块,该模块通过 配置信息,将dubbo组件的各个模块

其运行原理如下图所示。

![avatar](/Dubbo工作原理图.png)
![avatar](../../../images/Dubbo/Dubbo工作原理图.png)

### 工作原理
最后总结下其工作原理。
Expand Down
4 changes: 2 additions & 2 deletions docs/Dubbo/cluster/Dubbo集群模块简析.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@

下面我们来看一下 集群模块的项目结构图,结合上文的描述,可以对其有更加深刻的理解。

![avatar](/images/Dubbo/dubbo-cluster模块工程结构.png)
![avatar](../../../images/Dubbo/dubbo-cluster模块工程结构.png)

### 集群模块核心API 源码解析
从上图应该也能看出其核心API在哪个包里。

![avatar](/images/Dubbo/com.alibaba.dubbo.rpc.cluster包目录.png)
![avatar](../../../images/Dubbo/com.alibaba.dubbo.rpc.cluster包目录.png)

各核心接口的源码如下。
```java
Expand Down
8 changes: 4 additions & 4 deletions docs/Dubbo/registry/Dubbo注册中心模块简析.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
## 注册中心在Dubbo中的作用
服务治理框架可以大致分为 服务通信 和 服务管理 两部分,服务管理可以分为服务注册、服务订阅以及服务发现,服务提供者Provider 会往注册中心注册服务,而消费者Consumer 会从注册中心中订阅自己关注的服务,并在关注的服务发生变更时 得到注册中心的通知。Provider、Consumer以及Registry之间的依赖关系 如下图所示。

![avatar](/images/Dubbo/Dubbo工作原理图.png)
![avatar](../../../images/Dubbo/Dubbo工作原理图.png)

## dubbo-registry 模块 结构分析
dubbo的注册中心有多种实现方案,如:zookeeper、redis、multicast等,本章先看一下 dubbo-registry 模块的核心部分 dubbo-registry-api,具体实现部分放到下章来讲。dubbo-registry模块 的结构如下图所示。

![avatar](/images/Dubbo/dubbo-registry模块结构图.png)
![avatar](../../../images/Dubbo/dubbo-registry模块结构图.png)

### Registry 核心组件类图
典型的 接口 -> 抽象类 -> 实现类 的结构设计,如下图所示。

![avatar](/images/Dubbo/Registry组件类图.png)
![avatar](../../../images/Dubbo/Registry组件类图.png)

既然有Registry组件,那么按照很多框架的套路,肯定也有一个用于获取 Registry实例的RegistryFactory,其中用到了工厂方法模式,不同的工厂类用于获取不同类型的实例。其类图结构如下。

![avatar](/images/Dubbo/RegistryFactory组件类图.png)
![avatar](../../../images/Dubbo/RegistryFactory组件类图.png)

## 源码详解
根据上面的类图,我们开始从上往下 详解dubbo中对于注册中心的设计以及实现。
Expand Down
4 changes: 2 additions & 2 deletions docs/Dubbo/registry/注册中心的Zookeeper实现.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ Dubbo的注册中心 虽然提供了多种实现,但生产上的事实标准

由于 Dubbo 是一个分布式RPC开源框架,各服务之间单独部署,往往会出现资源之间数据不一致的问题,比如:某一个服务增加或减少了几台机器,某个服务提供者变更了服务地址,那么服务消费者是很难感知到这种变化的。而 Zookeeper 本身就有保证分布式数据一致性的特性。那么 Dubbo服务是如何被 Zookeeper的数据结构存储管理的呢,zookeeper采用的是树形结构来组织数据节点,它类似于一个标准的文件系统,如下图所示。

![avatar](/images/Dubbo/dubbo注册中心在zookeeper中的结构.png)
![avatar](../../../images/Dubbo/dubbo注册中心在zookeeper中的结构.png)

该图展示了dubbo在zookeeper中存储的形式以及节点层级。dubbo的Root层是根目录,通过<dubbo:registry group="dubbo" />的“group”来设置zookeeper的根节点,缺省值是“dubbo”。Service层是服务接口的全名。Type层是分类,一共有四种分类,分别是providers 服务提供者列表、consumers 服务消费者列表、routes 路由规则列表、configurations 配置规则列表。URL层 根据不同的Type目录:可以有服务提供者 URL 、服务消费者 URL 、路由规则 URL 、配置规则 URL 。不同的Type关注的URL不同。

zookeeper以斜杠来分割每一层的znode节点,比如第一层根节点dubbo就是“/dubbo”,而第二层的Service层就是/dubbo/com.foo.Barservice,zookeeper的每个节点通过路径来表示以及访问,例如服务提供者启动时,向/dubbo/com.foo.Barservice/providers目录下写入自己的URL地址。

dubbo-registry-zookeeper 模块的工程结构如下图所示,里面就俩类,非常简单。

![avatar](/images/Dubbo/dubbo-registry-zookeeper模块工程结构图.png)
![avatar](../../../images/Dubbo/dubbo-registry-zookeeper模块工程结构图.png)

### ZookeeperRegistry
该类继承了FailbackRegistry抽象类,针对注册中心核心的 服务注册、服务订阅、取消注册、取消订阅,查询注册列表进行展开,这里用到了 模板方法设计模式,FailbackRegistry中定义了register()、subscribe()等模板方法和 doRegister()、doSubscribe()抽象方法,ZookeeperRegistry基于zookeeper对这些抽象方法进行了实现。其实你会发现zookeeper虽然是最被推荐的,反而它的实现逻辑相对简单,因为调用了zookeeper服务组件,很多的逻辑不需要在dubbo中自己去实现。
Expand Down
4 changes: 2 additions & 2 deletions docs/JDK/Executor线程池组件.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
## 线程池核心组件图解
看源码之前,先了解一下该组件 最主要的几个 接口、抽象类和实现类的结构关系。

![avatar](/images/JDK1.8/线程池组件类图.png)
![avatar](../../images/JDK1.8/线程池组件类图.png)

该组件中,Executor 和 ExecutorService接口 定义了线程池最核心的几个方法,提交任务submit
()、关闭线程池shutdown()。抽象类 AbstractExecutorService 主要对公共行为 submit()系列方法进行了实现,这些 submit()方法 的实现使用了 模板方法模式,其中调用的 execute()方法 是未实现的 来自 Executor接口 的方法。实现类 ThreadPoolExecutor 则对线程池进行了具体而复杂的实现。
Expand Down Expand Up @@ -211,7 +211,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
```
ThreadPoolExecutor 中的 execute()方法 执行 Runnable任务 的流程逻辑可以用下图表示。

![avatar](/images/ConcurrentProgramming/线程池流程.png)
![avatar](../../../images/ConcurrentProgramming/线程池流程.png)

### 工具类 Executors
看类名也知道,它最主要的作用就是提供 static 的工具方法,为开发者提供各种封装好的 具有各自特性的线程池。
Expand Down
4 changes: 2 additions & 2 deletions docs/JDK/Lock锁组件.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
## 类图结构
J.U.C 的锁组件中 类相对较少,从JDK相应的包中也能看出来,下图标记了其中最主要的几个接口和类,也是本文要分析的重点。

![avatar](/images/JDK1.8/JUC的locks包.png)
![avatar](../../images/JDK1.8/JUC的locks包.png)

下图 将这几个接口和类 以类图的方式展现出来,其中包含了它们所声明的主要方法。

![avatar](/images/JDK1.8/JUC锁组件类图.png)
![avatar](../../images/JDK1.8/JUC锁组件类图.png)

## Lock 组件
Lock 组件的结构很简单,只有一个接口和一个实现类,源码如下。
Expand Down
2 changes: 1 addition & 1 deletion docs/JDK/Thread.md
Original file line number Diff line number Diff line change
Expand Up @@ -317,4 +317,4 @@ public class Thread implements Runnable {
```
之前一直对线程状态 及 状态切换的概念模糊不清,现在通过源码中对线程状态的定义,我们可以画张图来重新回顾一下,以使我们对其有更加深刻的理解。

![avatar](/images/JDK1.8/ThreadStatusChange.png)
![avatar](../../images/JDK1.8/ThreadStatusChange.png)
2 changes: 1 addition & 1 deletion docs/JDK/ThreadLocal.md
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ public class ThreadLocal<T> {
```
简单画个图总结一下 ThreadLocal 的原理,如下。

![avatar](/images/JDK1.8/ThreadLocal原理.png)
![avatar](../../images/JDK1.8/ThreadLocal原理.png)

最后强调一下 ThreadLocal的使用注意事项:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public class Singleton3 {
* 使用volatile修饰instance变量 可以 避免上述的指令重排
* tips:不太理解的是 第一个线程在执行第2步之前就已经释放了锁吗?导致其它线程进入synchronized代码块
* 执行 instance == null 的判断?
* 回答:第一个线程在执行第2步之前就已经释放了锁吗?(没有)。如果不使用volatile修饰instance变量,那么其他线程进来的时候,看到的instance就有可能不是null的,因为已经执行了第3步,那么此时这个线程(执行 return instance;)使用的instance是一个没有初始化的instance,就会有问题。
*/
private volatile static Singleton3 instance;

Expand Down Expand Up @@ -485,7 +486,7 @@ public class SmartTransformerFactoryImpl extends SAXTransformerFactory {
### 个人理解
该模式主要用于将复杂对象的构建过程分解成一个个简单的步骤,或者分摊到多个类中进行构建,保证构建过程层次清晰,代码不会过分臃肿,屏蔽掉了复杂对象内部的具体构建细节,其类图结构如下所示。

![avatar](/images/DesignPattern/建造者模式类图.png)
![avatar](../../../images/DesignPattern/建造者模式类图.png)

该模式的主要角色如下:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -812,7 +812,7 @@ class PooledConnection implements InvocationHandler {

装饰器模式能够帮助我们解决上述问题,装饰器可以动态地为对象添加功能,它是基于组合的方式实现该功能的。在实践中,我们应该尽量使用组合的方式来扩展系统的功能,而非使用继承的方式。通过装饰器模式的介绍,可以帮助读者更好地理解设计模式中常见的一句话:组合优于继承。下面先来看一下装饰器模式的类图,及其核心角色。

![avatar](/images/DesignPattern/装饰器模式类图.png)
![avatar](../../../images/DesignPattern/装饰器模式类图.png)

- Component (组件):组件接口定义了全部 “组件实现类” 以及所有 “装饰器实现” 的行为。
- ConcreteComponent (具体组件实现类):通常情况下,具体组件实现类就是被装饰器装饰的原始对象,该类提供了 Component 接口中定义的最基本的功能,其他高级功能或后续添加的新功能,都是通过装饰器的方式添加到该类的对象之上的。
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#### 个人理解
去年看了蛮多源码,发现 框架的开发者在实际使用设计模式时,大都会根据实际情况 使用其变体,老老实实按照书上的类图及定义去设计代码的比较少。不过我们依然还是先看一下书上的定义,然后比较一下理论与实践的一些差别吧。策略模式的类图及定义如下。

![avatar](/images/DesignPattern/策略模式类图.png)
![avatar](../../../images/DesignPattern/策略模式类图.png)

定义一系列算法,封装每个算法 并使它们可以互换。该模式的主要角色如下:

Expand Down Expand Up @@ -948,7 +948,7 @@ public class ArrayList<E> extends AbstractList<E>
#### 个人理解
这个模式也是平时很少使用的,所以就简单介绍一下,然后结合JDK中的源码加深理解。该模式用于定义对象之间的一对多依赖,当一个对象状态改变时,它的所有依赖都会收到通知,然后自动更新。类图和主要角色如下:

![avatar](/images/DesignPattern/观察者模式类图.png)
![avatar](../../../images/DesignPattern/观察者模式类图.png)

- Subject主题:具有注册、移除及通知观察者的功能,主题是通过维护一个观察者列表来实现这些功能的;
- Observer观察者:其注册需要Subject的registerObserver()方法。
Expand Down Expand Up @@ -1080,11 +1080,11 @@ public class Observable {

在责任链模式中,将上述臃肿的请求处理逻辑 拆分到多个 功能逻辑单一的 Handler 处理类中,这样我们就可以根据业务需求,将多个 Handler 对象组合成一条责任链,实现请求的处理。在一条责任链中,每个 Handler对象 都包含对下一个 Handler对象 的引用,一个 Handler对象 处理完请求消息(或不能处理该请求)时, 会把请求传给下一个 Handler对象 继续处理,依此类推,直至整条责任链结束。简单看一下责任链模式的类图。

![avatar](/images/DesignPattern/责任链模式.png)
![avatar](../../../images/DesignPattern/责任链模式.png)

#### Netty 中的应用
在 Netty 中,将 Channel 的数据管道抽象为 ChannelPipeline,消息在 ChannelPipeline 中流动和传递。ChannelPipeline 是 ChannelHandler 的容器,持有 I/O事件拦截器 ChannelHandler 的链表,负责对 ChannelHandler 的管理和调度。由 ChannelHandler 对 I/O事件 进行拦截和处理,并可以通过接口方便地新增和删除 ChannelHandler 来实现不同业务逻辑的处理。下图是 ChannelPipeline源码中描绘的责任链事件处理过程。
![avatar](/images/Netty/ChannelPipeline责任链事件处理过程.png)
![avatar](../../../images/Netty/ChannelPipeline责任链事件处理过程.png)
其具体过程处理如下:

1. 底层SocketChannel 的 read方法 读取 ByteBuf,触发 ChannelRead事件,由 I/O线程 NioEventLoop 调用 ChannelPipeline 的 fireChannelRead()方法,将消息传输到 ChannelPipeline中。
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ public class PoolState {
PooledDataSource 管理的数据库连接对象 是由其持有的 UnpooledDataSource对象 创建的,并由 PoolState 管理所有连接的状态。
PooledDataSource 的 getConnection()方法 会首先调用 popConnection()方法 获取 PooledConnection对象,然后通过 PooledConnection 的 getProxyConnection()方法 获取数据库连接的代理对象。popConnection()方法 是 PooledDataSource 的核心逻辑之一,其整体的逻辑关系如下图:

![avatar](/images/mybatis/数据库连接池流程图.png)
![avatar](../../../images/mybatis/数据库连接池流程图.png)

```java
public class PooledDataSource implements DataSource {
Expand Down
2 changes: 1 addition & 1 deletion docs/Mybatis/基础支持层/4、缓存模块.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public interface Cache {
```
如下图所示,Cache接口 的实现类有很多,但大部分都是装饰器,只有 PerpetualCache 提供了 Cache 接口 的基本实现。

![avatar](/images/mybatis/Cache组件.png)
![avatar](../../../images/mybatis/Cache组件.png)

### 1.1 PerpetualCache
PerpetualCache(Perpetual:永恒的,持续的)在缓存模块中扮演着被装饰的角色,其实现比较简单,底层使用 HashMap 记录缓存项,也是通过该 HashMap对象 的方法实现的 Cache接口 中定义的相应方法。
Expand Down
22 changes: 11 additions & 11 deletions docs/Mybatis/基础支持层/Mybatis-Reflector.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,13 +143,13 @@ class HfReflectorTest {

- 准备工作完成了开始进行 debug , 在`org.apache.ibatis.reflection.Reflector#addDefaultConstructor`这个方法上打上断点

![1575890354400](/images/mybatis/1575890354400.png)
![1575890354400](../../../images/mybatis/1575890354400.png)

观察`constructors`属性存在两个方法,这两个方法就是我在`People`类中的构造方法.

根据语法内容我们应该对`parameterTypes`属性进行查看

![1575890475839](/images/mybatis/1575890475839.png)
![1575890475839](../../../images/mybatis/1575890475839.png)

可以发现空参构造的`parameterTypes`长度是0.因此可以确认`org.apache.ibatis.reflection.Reflector#addDefaultConstructor`方法获取了空参构造

Expand Down Expand Up @@ -287,17 +287,17 @@ class HfReflectorTest {

- 照旧我们进行 debug 当前方法为`toString`方法

![1575891988804](/images/mybatis//1575891988804.png)
![1575891988804](../../../images/mybatis//1575891988804.png)

从返回结果可以看到`sb.toString`返回的是: `返回值类型#方法名`

![1575892046692](/images/mybatis//1575892046692.png)
![1575892046692](../../../images/mybatis//1575892046692.png)

上图返回结果为`void#setName:java.lang.String` 命名规则:`返回值类型#方法名称:参数列表`

回过头看看`uniqueMethods`里面是什么

![1575892167982](/images/mybatis//1575892167982.png)
![1575892167982](../../../images/mybatis//1575892167982.png)

方法签名:方法

Expand Down Expand Up @@ -325,11 +325,11 @@ class HfReflectorTest {

目标明确了就直接在

![1575892414120](/images/mybatis//1575892414120.png)
![1575892414120](../../../images/mybatis//1575892414120.png)

这里打断点了

![1575892511471](/images/mybatis//1575892511471.png)
![1575892511471](../../../images/mybatis//1575892511471.png)

在进入循环之前回率先加载本类的所有可见方法

Expand All @@ -342,15 +342,15 @@ class HfReflectorTest {

接下来断点继续往下走

![1575892645405](/images/mybatis//1575892645405.png)
![1575892645405](../../../images/mybatis//1575892645405.png)

走到这一步我们来看看`currentClass.getSuperclass()`是不是上一级的类

![1575892687076](/images/mybatis//1575892687076.png)
![1575892687076](../../../images/mybatis//1575892687076.png)

通过断点可见这个`currentClass`现在是`People`类,根据之前所说的最终`uniqueMethods`应该存在父类的方法

![1575892763661](/images/mybatis//1575892763661.png)
![1575892763661](../../../images/mybatis//1575892763661.png)

可以看到父类的方法也都存在了

Expand Down Expand Up @@ -431,4 +431,4 @@ class HfReflectorTest {

- 下图为一个类的解析结果

![1575894218362](/images/mybatis/1575894218362.png)
![1575894218362](../../../images/mybatis/1575894218362.png)
2 changes: 1 addition & 1 deletion docs/Mybatis/核心处理层/6、SqlSession组件.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public interface SqlSession extends Closeable {
### 1.1 DefaultSqlSession
DefaultSqlSession是单独使用MyBatis进行开发时,最常用的SqISession接口实现。其实现了SqISession接口中定义的方法,及各方法的重载。select()系列方法、selectOne()系列方法、selectList()系列方法、selectMap()系列方法之间的调用关系如下图,殊途同归,它们最终都会调用Executor的query()方法。

![avatar](/images/mybatis/DefaultSqlSession方法调用栈.png)
![avatar](../../../images/mybatis/DefaultSqlSession方法调用栈.png)

上述重载方法最终都是通过调用Executor的query(MappedStatement, Object, RowBounds,ResultHandler)方法实现数据库查询操作的,但各自对结果对象进行了相应的调整,例如:selectOne()方法是从结果对象集合中获取了第一个元素返回;selectMap()方法会将List类型的结果集 转换成Map类型集合返回;select()方法是将结果集交由用户指定的ResultHandler对象处理,且没有返回值;selectList()方法则是直接返回结果对象集合。
DefaultSqlSession的insert()方法、update()方法、delete()方法也有多个重载,它们最后都是通过调用DefaultSqlSession的update(String, Object)方法实现的,该重载首先会将dirty字段置为true,然后再通过Executor的update()方法完成数据库修改操作。
Expand Down
Loading

0 comments on commit 068196e

Please sign in to comment.