從上一篇Java SPI 機(jī)制解析?可以知道 Java SPI 的一些劣勢(shì)讽膏。Dubbo 的擴(kuò)展點(diǎn)加載從 Java SPI 擴(kuò)展點(diǎn)發(fā)現(xiàn)機(jī)制加強(qiáng)而來脑奠。
SPI實(shí)際上是“接口+策略模式+配置文件”實(shí)現(xiàn)的動(dòng)態(tài)加載機(jī)制美澳。在系統(tǒng)設(shè)計(jì)中植影,模塊之間通耻剑基于接口編程扰路,不直接顯示指定實(shí)現(xiàn)類。一旦代碼里指定了實(shí)現(xiàn)類谒亦,就無法在不修改代碼的情況下替換為另一種實(shí)現(xiàn)竭宰。為了達(dá)到動(dòng)態(tài)可插拔的效果,java提供了SPI以實(shí)現(xiàn)服務(wù)發(fā)現(xiàn)份招。
Dubbo的SPI
相關(guān)定義
ExtensionLoader切揭,是dubbo的SPI機(jī)制的查找服務(wù)實(shí)現(xiàn)的工具類,類似與Java的ServiceLoader脾还,可做類比伴箩。dubbo約定擴(kuò)展點(diǎn)配置文件放在classpath下的/META-INF/dubbo,/META-INF/dubbo/internal鄙漏,/META-INF/services目錄下嗤谚,配置文件名為接口的全限定名,配置文件內(nèi)容為配置名=擴(kuò)展實(shí)現(xiàn)類的全限定名怔蚌。
Demo走起~~~~~~~~~~~~~~
(1)接口和實(shí)現(xiàn)類
(2)使用Dubbo SPI的方式通過接口找實(shí)現(xiàn)類方式
a- 定義約定好的文件夾?
META-INF/dubbo/internal
b- 定義接口文件?
com.jack.DistributedArchitecture
c- 配置實(shí)現(xiàn)類
springcloud=com.yjy.SpringCloudImpl
dubbo=com.yjy.DubboImpl
servicemesh=com.yjy.ServiceMeshImpl
(3)模板代碼
ExtensionLoader extensionLoader =ExtensionLoader.getExtensionLoader(DistributedArchitecture.class);
DistributedArchitecture distributedArchitecture =extensionLoader.getExtension("xxx"); // key
distributedArchitecture.solve("家源技術(shù)");
源碼走讀
Dubbo SPI應(yīng)用場(chǎng)景
dubbo的 Filter很钓、Protocol九默、Cluster绷跑、LoadBalance 等都是通過 SPI 的方式進(jìn)行拓展加載的力奋。
Spring中的SPI機(jī)制
Spring中提供了SPI機(jī)制,我們只需要在 META-INF/spring.factories 中配置接口實(shí)現(xiàn)類名籍胯,即可通過服務(wù)發(fā)現(xiàn)機(jī)制竟闪,在運(yùn)行時(shí)加載接口的實(shí)現(xiàn)類:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration
在 spring-boot-autoconfigure 模塊下,SpringBoot默認(rèn)就配置了很多接口的服務(wù)實(shí)現(xiàn):
配置好 spring.factories 文件后杖狼,我們就可以通過 SpringFactoriesLoader 動(dòng)態(tài)加載接口實(shí)現(xiàn)類了炼蛤,代碼如下:
SpringFactoriesLoader API
org.springframework.core.io.support.SpringFactoriesLoader就是Spring框架中的“ServiceLoader”,該類提供了下列功能:
類靜態(tài)成員常量 final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories"
此常量定義了該工具類要從每個(gè)jar包中提取的工廠類定義屬性文件的相對(duì)路徑蝶涩。
類靜態(tài)方法 <T> List<T> loadFactories(Class<T> factoryClass, ClassLoader classLoader)
此方法會(huì)讀取classpath上所有的jar包中的所有 META-INF/spring.factories 屬性文件理朋,找出其中定義的匹配類型 factoryClass 的工廠類絮识,然后創(chuàng)建每個(gè)工廠類的對(duì)象/實(shí)例,并返回這些工廠類對(duì)象/實(shí)例的列表嗽上。
類靜態(tài)方法 List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader)
此方法會(huì)讀取classpath上所有的jar包中的所有 META-INF/spring.factories 屬性文件次舌,找出其中定義的匹配類型 factoryClass 的工廠類,然后并返回這些工廠類的名字列表兽愤,注意是包含包名的全限定名彼念。
SpringFactoriesLoader 源碼
SpringBoot2.7.0 自動(dòng)配置將不推薦使用spring.factories
SpringBoot 2.7 中,不再推薦使用/META-INF/spring.factories文件作為自動(dòng)配置類的配置文件烹看,所以對(duì)于有自定義Starter的開發(fā)者來說国拇,有時(shí)間要抓緊把這一變化改起來了洛史,因?yàn)樵赟pringBoot 3開始將移除對(duì)/META-INF/spring.factories的支持惯殊。
如果您已經(jīng)創(chuàng)建了自動(dòng)配置,那么應(yīng)該將注冊(cè)從META-INF/spring.factories轉(zhuǎn)移到一個(gè)名為META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports的新文件也殖。每一行都包含自動(dòng)配置的完全限定名土思。