创意电子
标题:
Dubbo 源码分析
[打印本页]
作者:
指尖代码
时间:
2021-9-22 00:00
标题:
Dubbo 源码分析
最近准备对Dubbo的历史毛病进行分析,但以为不懂Dubbo的设计和实现直接去分析毛病比较困难,以是在分析毛病前先分析Dubbo的源码及实现,值得一提的是Dubbo的官网也有非常详细的源码分析的过程。
SPI机制及实现
Dubbo的SPI是对JDK自身SPI的扩展实现,增加了IOC和AOP的功能,是Dubbo实现的核心,Dubbo SPI必要的配置文件放在
/meta- inf/dubbo
目次下,通过键值对的方式配置,如下所示:
adaptive=org.apache.dubbo.common.extension.factory.AdaptiveExtensionFactoryspi=org.apache.dubbo.common.extension.factory.SpiExtensionFactory
Dubbo的SPI和JDK自身的SPI对好比下,这也是Dubbo没有选择使用JDK自带SPI的原因。
登录/注册后可看大图
可以通过
@SPI
注解将接口声明由Dubbo的SPI机制加载实现类。
登录/注册后可看大图
Dubbo如何实现SPI?
ExtensionLoader
是Dubbo
SPI实现的核心类,每个界说的spi的接口都会构建一个ExtensionLoader实例。一般通过
ExtensionLoader.getExtensionLoader
获取ExtensionLoader实例。
getExtensionLoader
首先判断是否为接口类型并且由
@SPI
注解修饰,也就是说只有
@SPI
修饰的接谈锋会由Dubbo的SPI机制去寻找实现类。下面会通过
EXTENSION_LOADERS
寻找是否已经有loader的实例,没有的话会创建一个并添加到
EXTENSION_LOADERS
中。
登录/注册后可看大图
下面分析
ExtensionLoader
构造方法,假如type类型不为
ExtensionFactory
则先实行
ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()
登录/注册后可看大图
getAdaptiveExtension
首先从缓存中获取实例,没有则通过
createAdaptiveExtension
创建实例。
登录/注册后可看大图
createAdaptiveExtension
首先通过
getAdaptiveExtensionClass().newInstance()
创建实例,再通过
injectExtension
包装。
登录/注册后可看大图
getAdaptiveExtensionClass
首先通过
getExtensionClasses
获取Class,找不到则通过
createAdaptiveExtensionClass
创建。
登录/注册后可看大图
getExtensionClasses
首先通过缓存获取Class获取不到则通过
loadExtensionClasses
方法获取,获取后放到
classes
Map中。
登录/注册后可看大图
loadExtensionClasses
首先获取SPI注解的属性值放到缓存中,下面通过
loadDirectory
从配置文件中加载Class,主要从
META- INF/dubbo/
、
META-INF/services/
、
META-INF/dubbo/internal
几个目次下加载文件。
登录/注册后可看大图
登录/注册后可看大图
根据dir和type作为文件名加载资源,并通过
loadResource
加载类的信息并放到
extensionClasses
中。
登录/注册后可看大图
loadResource
中读取文件并解析文件内容获取
name
和
接口实现类的名称
,下面通过
loadClass
加载。
登录/注册后可看大图
在
loadClass
中首先查抄
clazz
是否是type的实现类,再去检测clazz的接口是否有
Adaptive
注解存在的话放到将类放到
cachedAdaptiveClass
缓存中,下面再通过是否有参数为
clazz
的构造方法,有的话将clazz存到
cachedWrapperClasses
中,下面查看实现类是否有
Extension
注解,有的话取出这个注解的值并赋值给name。下面获取name的值,可以通过
xxx,xxx,xx=xxx.com
等形式传入多个name,并通过
saveInExtensionClass
将
name
和
class
的值保存到
extensionClasses
中。
登录/注册后可看大图
下面在回到
getAdaptiveExtensionClass
方法中,首先在缓存中查找,找不到则会通过
createAdaptiveExtensionClass
创建Class。
登录/注册后可看大图
createAdaptiveExtensionClass
首先根据
type
和
SPI配置的value
的值生成Adaptive包装类并编译为Class,也就是说我们获取的类型不是配置的实现类对象,而是Adaptive包装类对象。
登录/注册后可看大图
生成代码的逻辑比较复杂,我们就不深入分析了,不外我们可以拿到生成的代码,可以看看生成的代码主要做了什么。首先它是type接口的实现类,假如接口中的方法没有通过
Adaptive
修饰,则直接抛出异常。
登录/注册后可看大图
对于
Adaptive
注解修饰的方法则会生成实现,首先查抄Invoker的url是否为空,再获取协议信息,假如没有配置协议则默认使用
dubbo
协议,下面获取Protocol的实现类并实行实现类的export方法,实在也就是对export进行了一些包装,在实行export前加了一些验证逻辑。
登录/注册后可看大图
refer
方法逻辑雷同,只是最后调用实现类的
refer
方法。
登录/注册后可看大图
下面我们再回到
createAdaptiveExtension
方法中,通过
getAdaptiveExtensionClass()
已经拿到了动态创建的
Adaptive
类并通过
newInstance创建对象
,下面通过
injectExtension
完成依赖注入。
登录/注册后可看大图
如何实现IOC?
injectExtension
获取setter方法,并通过
objectFactory.getExtension(pt, property);
获取必要注入的对象,通过反射调用setter方法完成依赖注入。
登录/注册后可看大图
objectFactory
可能是下面三种实现类,也就是说除了可以通过
Spi
获取注入的对象也可以从spring中获取注入对象。而
AdaptiveExtensionFactory
则会循环调用多个factory获取对象。
登录/注册后可看大图
一般objectFactory经过初始化后会封装为
AdaptiveExtensionFactory
并且包罗了
spi
和
spring
两个工厂,也就是说默认会通过
spi
和
spring
两种方式加载必要注入的对象。
登录/注册后可看大图
为什么可以得到AdaptiveExtentionFactory?
<span style="letter-spacing: 1px;">
在容器启动时,会解析
<span style="color: #858080; --tt-darkmode-color: #858080;">
欢迎光临 创意电子 (https://wxcydz.cc/)
Powered by Discuz! X3.4