ExtensionFactory的實現原理
RegistryFactory工廠類通過@Adaptive({"protocol"})
註解動態查找註冊中心實現,根據URL中的protocol參數動態選擇對應的註冊中心工廠,並初始化具體的註冊中心客戶端。而實現這個特性的ExtensionLoader類,本身又是通過工廠方法ExtensionFactory創建的,並且這個工廠接口上也有SPI註解,還有多個實現。
AdaptiveExtensionFactory這個實現類工廠上有@Adaptive註解。因此,AdaptiveExtensionFactory會作爲一開始的默認實現。
工廠類之間的關係如下:
可以看到,除了可以從Dubbo SPI管理的容器中獲取擴展點實例,還可以從Spring容器中獲取。
Dubbo和Spring容器之間是如何打通的呢?
看SpringExtensionFactory的實現,該工廠提供了保存Spring上下文的靜態方法,可以把Spring上下文保存到Set集合中。當調用getExtension獲取擴展類時,會遍歷Set集合中所有的Spring上下文,先根據名字依次從每個Spring容器中進行匹配,如果根據名字沒匹配到,則根據類型去匹配,如果還沒有匹配到則返回null:
再看SPIExtensionFactory,主要就是獲取擴展點接口對應的Adaptive實現類。例如:某個擴展點實現類ClassA上有@Adaptive註解,則調用SpiExtensionFactory#getExtesion會直接返回ClassA實例:
經過一番流轉,最終還是回到了默認實現AdaptiveExtensionFactory上,因爲該工廠上有@Adaptive註解。這個默認工廠在構造方法中就獲取了所有擴展類工廠並緩存起來,包括SpiExtensionFactory和SpringExtensionFactory。
被AdaptiveExtensionFactory緩存的工廠會通過TreeSet進行排序,SPI排在前面,Spring排在後面。當調用getExtension方法時,會遍歷所有的工廠,先從SPI容器中獲取擴展類,如果沒找到,則再從Spring容器中查找。
可以理解爲,AdaptiveExtensionFactory持有了所有的具體工廠實現,它的getExtesion方法中只是遍歷了它持有的所有工廠,最終還是調動SPI或Spring工廠實現的getExtesion方法。