1.模块划分
2.基于spring 配置文件的扩展
3.源码分析
1)解析配置文件
2)服务端 ServiceBean
3)消费端 ReferenceBean
4)ExtensionLoader分析
4.dubbo插件化
1.模块划分
dubbo-cluster 负载均衡 loadbalance
NamespaceHandler: 注册BeanDefinitionParser, 利用它来解析
BeanDefinitionParser: 解析配置文件的元素、
参考:https://www.cnblogs.com/jifeng/archive/2011/09/14/2176599.html
Main.main(args) 这个方法只是启动了容器,重要的入口在配置文件
因为dubbo是基于spring扩展的,所以我们找到dubbo-config
spring会默认加载jar包下/META-INF/spring.handlers 找到对应的NamespaceHandler,这个就是入口
DubboBeanDefinitionParser.parse 解析配置,对一些特殊节点进行特殊处理,返回beanDefinition
配置解析完之后怎么发布呢?我们继续看其他的类,找到了属性的ServiceBean与ReferenceBean
initializingBean,当spring容器初始化完以后,会调用afterPropertiesSet方法
DisposableBean, 在Spring BeanFactory销毁一个单例实例之前调用
ApplicationContextAwarer, spring初始化完之后会注入ApplicationContext对象
ApplicationListener, spring容器启动后会触发事件通知
BeanNameAware bean初始化完之后会获得bean本身的一些属性
>afterPropertiesSet:读取配置文件如果为空,dubbo会做一些自己的处理,不依赖spring
->afterPropertiesSet.export 发布,含延迟发布,通过守护线程(下面是发布的流程)
---->DubboProtocol.export->openServer->createServer 查看使用dubbo协议发布的流程
----->Exchangers.bind(url, requestHandler);->getExchanger(url).bind(url, handler)->... 一直追踪bind方法
------>new NettyServer(url, listener)->doOpen 查看到最后bind是调用启动了一个netty
参考 https://www.cnblogs.com/huqianliang/articles/5673661.html
>afterPropertiesSet:读取配置文件如果为空,dubbo会做一些自己的处理,不依赖spring
->getObject()->...->init()->createProxy(map) 创建代理
-->proxyFactory.getProxy(invoker)
当用户调用service时dubbo会通过InvokerProxy调用Invoker的invoke的方法向服务端发起请求。客户端就这样完成了自己的初始化
参考 https://blog.csdn.net/prestigeding/article/details/80621535
com.alibaba.dubbo.common.extension
1. com.alibaba.dubbo.common.extension
4. | |--AdaptiveExtensionFactory #稍后解释
5. | |--SpiExtensionFactory #稍后解释
12. |--ExtensionFactory #扩展点对象生成工厂接口
13. |--ExtensionLoader #扩展点加载器,扩展点的查找,校验,加载等核心逻辑的实现类
2)其中最核心的类就是ExtensionLoader,几乎所有特性都在这个类中实现。
ExtensionLoader没有提供public的构造方法,但是提供了一个public static的getExtensionLoader,这个方法就是获取ExtensionLoader实例的工厂方法。其public成员方法中有三个比较重要的方法:
getActivateExtension :根据条件获取当前扩展可自动激活的实现
getExtension : 根据名称获取当前扩展的指定实现
getAdaptiveExtension : 获取当前扩展的自适应实现
3)参考:https://blog.csdn.net/jdluojing/article/details/44947221
在整个过程中,最重要的两个方法getExtensionClasses和createAdaptiveExtensionClass
这个方法主要是读取META-INF/services 、META-INF/dubbo、META-INF/internal目录下的文件内容
分析每一行,如果发现其中有哪个类的annotation是@Adaptive,就找到对应的AdaptiveClass。如果没有的话,就动态创建一个
该方法是在getExtensionClasses方法找不到AdaptiveClass的情况下被调用,该方法主要是通过字节码的方式在内存中新生成一个类,它具有AdaptiveClass的功能,Protocol就是通过这种方式获得AdaptiveClass类的。
Dubbo的插件化实现非常类似于原生的JAVA的SPI:它只是提供一种协议,并没有提供相关插件化实施的接口。用过的同学都知道,它有一种java原生的支持类:ServiceLoader,通过声明接口的实现类,在META-INF/services中注册一个实现类,然后通过ServiceLoader去生成一个接口实例,当更换插件的时候只需要把自己实现的插件替换到META-INF/services中即可。
参考java SPI https://www.cnblogs.com/lovesqcc/p/5229353.html
Dubbo的SPI并非原生的SPI,Dubbo的规则是在META-INF/dubbo、META-INF/dubbo/internal或者META-INF/services下面以需要实现的接口去创建一个文件,并且在文件中以properties规则一样配置实现类的全面以及分配实现的一个名称。我们看一下dubbo-cluster模块的META-INF.dubbo.internal:
1.在resources目录下新建META-INF/dubbo/com.alibaba.dubbo.rpc.Protocol文件,文件内容为com.***.MyDefineProtocol
官网教程:http://dubbo.apache.org/#!/docs/dev/impls/protocol.md?lang=zh-cn