程序猿成长之路少不了要学习和分析源码的。最近难得能静得下心来,就针对dubbox为目标开始进行源码分析。
【服务提供方】
步骤 | 调用顺序 | 备注 |
容器启动 | com.alibaba.dubbo.container.Main.main(args); [dubbo-container-spring] SpringContainer.java -> [服务提供方]classpath*:META-INF/spring/*.xml -> dubbo.xsd | spring的 ApplicationContext介绍 |
bean初始化 | <dubbo:service>等自定义标签 -> [dubbo-config-spring] DubboNamespaceHandler.java spring对bean的初始化操作 [dubbo-config-spring] ServiceBean.java -> afterPropertiesSet() | 自定义标签的解析和初始化 |
连接注册中心 | ServiceBean.export() -> ServiceConfig.java -> doExportUrlsFor1Protocol() -> 暴露协议protocol.export() protocol=ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension()---Protocol$Adaptive.java protocol.export()调用链 -> [dubbo-registry-api] RegistryProtocol.export() | 注册到注册中心, 并加入监听列表监听注册中心的消息通知。 |
启动协议服务器 | protocol.export()调用链 -> [dubbo-rpc-rest] RestProtocol.export() -> doExport() -> server.start(), server.deploy() | 根据相应协议启动相应服务器 |
【服务使用方】
步骤 | 调用顺序 | 备注 |
容器启动 | 参考服务提供方 | 同provider |
bean初始化 | <dubbo:reference>等自定义标签 -> [dubbo-config-spring] DubboNamespaceHandler.java | 同provider |
连接注册中心 | ReferenceBean.java -> afterPropertiesSet() -> ReferenceConfig.init() -> createProxy() -> refprotocol.refer() refprotocol=ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension()---Protocol$Adaptive.java protocol.refer()调用链 -> [dubbo-registry-api] RegistryProtocol.refer() | 同provider |
服务接口初始化 | ReferenceConfig.init() -> createProxy() service接口在实际运行时是 com.alibaba.dubbo.common.bytecode.Proxy 类的实例 | 同provider |
总结与收获
很多细节由于时间关系没有展开,比如重试机制,比如比较重要的类的整理。整个分析的过程还是很多收获与启发的。
比如url.putParameter()每次设置参数却返回了一个新的对象,算是一种copyOnWrite的简单实现。
又比如几个比较重要的类都通过ExtensionLoader实现了动态扩展,可以理解为一种引擎或一种类加载器扩展,启动时动态扫描@Adaptive注解和配置文件,所以各个模块只要修改配置就可以实现filter, listener和mock的扩展。
再比如,典型的代理模式的应用,consumer都是通过反射生成服务接口的代理实例,实现远程调用provider,而调用的协议都是可变可扩展的。观察者模式就更随处可见了。