程序猿成長之路少不了要學習和分析源碼的。最近難得能靜得下心來,就針對dubbox為目標開始進行源碼分析。
com.alibaba.dubbo.container.Main.main(args);
dubbo.properties -> dubbo.container -> container.start()
container -> spring, log4j, jetty...
[dubbo-container-spring] SpringContainer.java -> [服務提供方]classpath*:META-INF/spring/*.xml -> dubbo.xsd
spring的 ApplicationContext介紹
bean初始化<dubbo:service>等自定義標簽 -> [dubbo-config-spring] DubboNamespaceHandler.java
-> new DubboBeanDefinitionParser(ServiceBean.class, true)
spring對bean的初始化操作
[dubbo-config-spring] ServiceBean.java -> afterPropertiesSet()
-> setProvider(), setApplication(), setModule(), setRegistries, setMonitor(), setProtocols, setPath() -> export()
ServiceBean.export() -> ServiceConfig.java -> doExportUrlsFor1Protocol() -> 暴露協議protocol.export()
protocol=ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension()---Protocol$Adaptive.java
-> ExtensionLoader.loadExtensionClasses() -> loadFile()
-> META-INF/dubbo/internal/,META-INF/dubbo/,META-INF/services/
-> [舉例dubbo-rpc-api] 配置文件com.alibaba.dubbo.rpc.Protocol
-> filter,listener,mock -> 各類的export()
protocol.export()調用鏈 -> [dubbo-registry-api] RegistryProtocol.export()
-> getRegistry()---(ZookeeperRegistry.java -> 擴展的ZookeeperClient)
-> registry.subscribe()加入監聽列表
<dubbo:reference>等自定義標簽 -> [dubbo-config-spring] DubboNamespaceHandler.java
-> new DubboBeanDefinitionParser(ReferenceBean.class, false)
ReferenceBean.java -> afterPropertiesSet() -> ReferenceConfig.init() -> createProxy() -> refprotocol.refer()
refprotocol=ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension()---Protocol$Adaptive.java
-> ExtensionLoader.loadExtensionClasses() -> loadFile()
-> META-INF/dubbo/internal/,META-INF/dubbo/,META-INF/services/
-> [舉例dubbo-rpc-api] com.alibaba.dubbo.rpc.Protocol -> filter,listener,mock -> 各類的refer()
protocol.refer()調用鏈 -> [dubbo-registry-api] RegistryProtocol.refer()
-> getRegistry()---(ZookeeperRegistry.java -> 擴展的ZookeeperClient) -> doRefer()
-> RegistryDirectory.subscribe() -> registry.subscribe()
ReferenceConfig.init() -> createProxy()
-> AbstractProxyFactory.getProxy() -> JavassistProxyFactory.getProxy()
service接口在實際運行時是 com.alibaba.dubbo.common.bytecode.Proxy 類的實例
同provider很多細節由於時間關系沒有展開,比如重試機制,比如比較重要的類的整理。整個分析的過程還是很多收獲與啟發的。
比如url.putParameter()每次設置參數卻返回了一個新的對象,算是一種copyOnWrite的簡單實現。
又比如幾個比較重要的類都通過ExtensionLoader實現了動態擴展,可以理解為一種引擎或一種類加載器擴展,啟動時動態掃描@Adaptive注解和配置文件,所以各個模塊只要修改配置就可以實現filter, listener和mock的擴展。
再比如,典型的代理模式的應用,consumer都是通過反射生成服務接口的代理實例,實現遠程調用provider,而調用的協議都是可變可擴展的。觀察者模式就更隨處可見了。