程式猿成長之路少不了要學習和分析源碼的。最近難得能靜得下心來,就針對dubbox為目標開始進行源碼分析。 【服務提供方】 com.alibaba.dubbo.container.Main.main(args);dubbo.properties -> dubbo.container -> contai ...
程式猿成長之路少不了要學習和分析源碼的。最近難得能靜得下心來,就針對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,而調用的協議都是可變可擴展的。觀察者模式就更隨處可見了。