3.dubbo源码分析

1.模块划分
2.基于spring 配置文件的扩展
3.源码分析
1)解析配置文件
2)服务端 ServiceBean
3)消费端 ReferenceBean
4)ExtensionLoader分析
4.dubbo插件化

1.模块划分

dubbo-admin 控制台

dubbo-cluster 负载均衡 loadbalance

dubbo-common 工具模块

dubbo-config spring配置的集成

dubbo-contrainer 容器

dubbo-demo 例子

dubbo-filter 过滤器(验证与缓存过滤)

dubbo-registry 注册中心

dubbo-remoting 通讯

dubbo-rpc 远程传输协议

dubbo-simple 简单监控中心

hessian-lite 改造hessian

2.基于spring 配置文件的扩展

1)编写xsd

2)编写两个类

NamespaceHandler: 注册BeanDefinitionParser, 利用它来解析

BeanDefinitionParser: 解析配置文件的元素、

参考:https://www.cnblogs.com/jifeng/archive/2011/09/14/2176599.html

3.源码分析

Main.main(args) 这个方法只是启动了容器,重要的入口在配置文件

因为dubbo是基于spring扩展的,所以我们找到dubbo-config

spring会默认加载jar包下/META-INF/spring.handlers  找到对应的NamespaceHandler,这个就是入口

1)解析配置文件

DubboNamespaceHandler

DubboBeanDefinitionParser.parse 解析配置,对一些特殊节点进行特殊处理,返回beanDefinition

配置解析完之后怎么发布呢?我们继续看其他的类,找到了属性的ServiceBean与ReferenceBean

2)服务端 ServiceBean

由于ServiceBean实现了下面几个接口

initializingBean,当spring容器初始化完以后,会调用afterPropertiesSet方法

DisposableBean, 在Spring BeanFactory销毁一个单例实例之前调用

ApplicationContextAwarer,  spring初始化完之后会注入ApplicationContext对象

ApplicationListener,  spring容器启动后会触发事件通知

BeanNameAware bean初始化完之后会获得bean本身的一些属性

第二个入口

>afterPropertiesSet:读取配置文件如果为空,dubbo会做一些自己的处理,不依赖spring

->afterPropertiesSet.export 发布,含延迟发布,通过守护线程(下面是发布的流程)

--->export .doExportUrls

---->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

3)消费端 ReferenceBean

类似serviceBean

>afterPropertiesSet:读取配置文件如果为空,dubbo会做一些自己的处理,不依赖spring

->getObject()->...->init()->createProxy(map)  创建代理

-->proxyFactory.getProxy(invoker)

当用户调用service时dubbo会通过InvokerProxy调用Invoker的invoke的方法向服务端发起请求。客户端就这样完成了自己的初始化

参考 https://blog.csdn.net/prestigeding/article/details/80621535

4)ExtensionLoader分析

dubbo的扩展点框架主要位于这个包下:

    com.alibaba.dubbo.common.extension

1)大概结构如下:   

1. com.alibaba.dubbo.common.extension  

2.  |  

3.  |--factory  

4.  |     |--AdaptiveExtensionFactory   #稍后解释  

5.  |     |--SpiExtensionFactory        #稍后解释  

6.  |  

7.  |--support  

8.  |     |--ActivateComparator  

9.  |  

10.  |--Activate  #自动激活加载扩展的注解  

11.  |--Adaptive  #自适应扩展点的注解  

12.  |--ExtensionFactory  #扩展点对象生成工厂接口  

13.  |--ExtensionLoader   #扩展点加载器,扩展点的查找,校验,加载等核心逻辑的实现类  

14.  |--SPI   #扩展点注解 

2)其中最核心的类就是ExtensionLoader,几乎所有特性都在这个类中实现。

ExtensionLoader没有提供public的构造方法,但是提供了一个public static的getExtensionLoader,这个方法就是获取ExtensionLoader实例的工厂方法。其public成员方法中有三个比较重要的方法:

getActivateExtension :根据条件获取当前扩展可自动激活的实现

getExtension : 根据名称获取当前扩展的指定实现

getAdaptiveExtension : 获取当前扩展的自适应实现

3)参考:https://blog.csdn.net/jdluojing/article/details/44947221

4)总结

在整个过程中,最重要的两个方法getExtensionClasses和createAdaptiveExtensionClass

getExtensionClasses

这个方法主要是读取META-INF/services 、META-INF/dubbo、META-INF/internal目录下的文件内容

分析每一行,如果发现其中有哪个类的annotation是@Adaptive,就找到对应的AdaptiveClass。如果没有的话,就动态创建一个

createAdaptiveExtensionClass

该方法是在getExtensionClasses方法找不到AdaptiveClass的情况下被调用,该方法主要是通过字节码的方式在内存中新生成一个类,它具有AdaptiveClass的功能,Protocol就是通过这种方式获得AdaptiveClass类的。

4.dubbo插件化

1)Dubbo插件化

Dubbo的插件化实现非常类似于原生的JAVA的SPI:它只是提供一种协议,并没有提供相关插件化实施的接口。用过的同学都知道,它有一种java原生的支持类:ServiceLoader,通过声明接口的实现类,在META-INF/services中注册一个实现类,然后通过ServiceLoader去生成一个接口实例,当更换插件的时候只需要把自己实现的插件替换到META-INF/services中即可。

参考java SPI https://www.cnblogs.com/lovesqcc/p/5229353.html

2)Dubbo的SPI

Dubbo的SPI并非原生的SPI,Dubbo的规则是在META-INF/dubbo、META-INF/dubbo/internal或者META-INF/services下面以需要实现的接口去创建一个文件,并且在文件中以properties规则一样配置实现类的全面以及分配实现的一个名称。我们看一下dubbo-cluster模块的META-INF.dubbo.internal:

实现自己的扩展点

假如我们使用自己定义的协议MyDefineProtocol

1.在resources目录下新建META-INF/dubbo/com.alibaba.dubbo.rpc.Protocol文件,文件内容为com.***.MyDefineProtocol

2.实现类的内容

3.最后在main方法中调用

官网教程:http://dubbo.apache.org/#!/docs/dev/impls/protocol.md?lang=zh-cn

猜你喜欢

转载自blog.csdn.net/CharJay_Lin/article/details/81604922