提到dubbo必須提到SPI爆哑。網(wǎng)絡(luò)上有很多介紹SPI原理的文章呻待,我不多介紹了砰盐。我介紹一下SPI的流程肿仑。官方文檔介紹:
http://dubbo.apache.org/zh-cn/docs/source_code_guide/dubbo-spi.html
SPI提供了一種插件功能谈撒,對于服務(wù)組件可以替換腥泥。dubbo的各層中,除了服務(wù)代理層和配置層之外啃匿,其他層組件都可以使用SPI替換蛔外。
下面的流程圖以代碼ExtensionLoader.getExtensionLoader(Container.class).getExtension("spring")為例。
上圖中提到的搜索文件和目錄可以參考代碼ExtensionLoader.loadExtensionClasses溯乒,這個方法指定了搜索目錄:
META-INF/dubbo/internal/
META-INF/dubbo/
META-INF/services/
搜索的文件名為ExtensionLoader.getExtensionLoader方法入?yún)⒌娜薅惷醒帷@缛雲(yún)ontainer.class,那么對應(yīng)的文件名是org.apache.dubbo.container.Container裆悄。
當(dāng)我們要搜索的內(nèi)容不在文件中時矛纹,比如搜索數(shù)據(jù)庫,可以重寫loadExtensionClasses方法查詢數(shù)據(jù)庫光稼。不過這樣我們需要修改源代碼或南。
文件org.apache.dubbo.container.Container里面的內(nèi)容如下:
spring=org.apache.dubbo.container.spring.SpringContainer
log4j=org.apache.dubbo.container.log4j.Log4jContainer
logback=org.apache.dubbo.container.logback.LogbackContainer
方法getExtension的入?yún)⑹俏募锩婷恳恍械忍柷懊娴闹怠?/p>
方法getExtensionLoader的入?yún)榻涌诤⒌龋褂肧PI加載對象,接口必須有SPI注解采够。SPI注解的value值表示要加載對象的默認(rèn)名字肄方。可以使用getDefaultExtension方法加載默認(rèn)名字對應(yīng)的對象蹬癌。比如Container接口默認(rèn)對象名字是spring权她,如果使用getDefaultExtension方法加載對象,那么和getExtension("spring")加載的對象是一樣的逝薪。
除了getDefaultExtension隅要,getExtension方法,還有g(shù)etActivateExtension和getAdaptiveExtension翼闽。
getActivateExtension可以加載多個對象拾徙,可以參考接口Filter。要求接口的實(shí)現(xiàn)類必須有Activate注解感局,如果注解的value和group與getActivateExtension入?yún)⒁恢履岱龋敲磄etActivateExtension方法會返回一個List集合。
getAdaptiveExtension方法一般會通過代碼生成模塊生成一個Adaptive類型的類询微,并實(shí)例化對象崖瞭。代碼生成是AdaptiveClassCodeGenerator類完成的。Adaptive類型的類方法需要有Adaptive注解撑毛,沒有Adaptive注解的方法在自動生成的代碼里面會拋出UnsupportedOperationException书聚。Adaptive類型的對象是自適應(yīng)對象,Adaptive注解的方法入?yún)⑹荱RL或者包含URL屬性的對象藻雌,Adaptive注解的value值為URL的屬性名雌续,屬性名對應(yīng)的值就是要加載的對象名,如果URL中不包含Adaptive注解指定的值胯杭,那么使用Adaptive類型類的接口的SPI注解的value值作為默認(rèn)值驯杜。