dubbo是一款微服務開發框架,它提供了 RPC通訊 與 微服務治理 兩大關鍵能力。作為spring cloud alibaba體系中重要的一部分,隨著spring cloud alibaba在國內活躍起來,dubbo也越來越深受各大公司的青睞。本文就來對dubbo的spi機制原始碼進行剖析,看一看dubbo的spi到底有哪些特性和功能。
SPI (Service Provider Interface),主要用於擴充套件的作用。舉個例子來說,假如有一個框架有一個介面,他有自己預設的實現類,但是在程式碼執行的過程中,你不想用他的實現類或者想擴充套件一下他的實現類的功能,但是此時你又不能修改別人的原始碼,那麼此時該怎麼辦?這時spi機制就有了用武之地。一般框架的作者在設計這種介面的時候不會直接去new這個介面的實現類,而是在Classpath路徑底下將這個介面的實現類按作者約定的格式寫在一個組態檔上,然後在執行的過程中通過java提供的api,從所有jar包中讀取所有的這個指定檔案中的內容,獲取到實現類,用這個實現類,這樣,如果你想自己替換原有的框架的實現,你就可以按照作者規定的方式設定實現,這樣就能使用你自己寫的實現類了。
spi機制其實體現了設計思想中的解耦思想,方便開發者對框架功能進行擴充套件。
java中最常見的spi機制應用就是資料庫驅動的載入,java其實就是定義了java語言跟資料庫互動的介面,但是具體的實現得交給各巨量資料庫廠商來實現,那麼java怎麼知道你的資料庫廠商的實現了?這時就需要spi機制了,java好約了定在 Classpath 路徑下的 META-INF/services/ 目錄裡建立一個以服務介面命名的檔案,然後內容是該資料庫廠商的實現的介面的全限定名,這樣資料庫廠商只要按照這個規則去設定,java就能找到。
我以mysql來舉例,看一下mysql是怎麼實現的。
內容
java是通過ServiceLoader類來實現讀取組態檔中的實現類的。大家有興趣可以看一下里面的程式碼,其實就是讀取到每個jar包底下的檔案,讀取裡面的內容。
相信spring大家都不陌生,在spring擴充套件也是依賴spi機制完成的,只不過spring對於擴充套件檔案約定在Classpath 路徑下的 META-INF目錄底下,所有的檔名都是叫spring.factories,檔案裡的內容是一個以一個個鍵值對的方式儲存的,鍵為類的全限定名,值也為類的全限定名,如果有多個值,可以用逗號分割,有一點得注意的是,鍵和值本身約定並沒有類與類之間的依賴關係(當然也可以有,得看使用場景的約定),也就是說鍵值可以沒有任何關聯,鍵僅僅是一種標識,代表一種場景,最常見的自動裝配的註解,@EnableAutoConfiguration,也就是代表自動裝配的場景,當你需要你的類被自動裝配,就可以以這個註解的許可權定名鍵,你的類為名,這樣springboot在進行自動裝配的時候,就會拿這個鍵,找到你寫的實現類來完成自動裝配。
這裡我貼出了自動裝配時載入類的原始碼。
這裡其實就是通過@EnableAutoConfiguration的全限定名從spring.factories中載入這個鍵對應的所有的實現類的名稱,這樣就能拿到所有需要自動裝配的類的全限定名了。
mybatis整合spring的自動裝配功能檔案
呼叫 ExtensionPostProcessor的postProcessBeforeInitialization方法,ExtensionPostProcessor跟spring中的BeanPostProcessor有點像,就是對目標物件進行擴充套件的作用。
可以看出,先通過反射獲取到所有的方法,然後遍歷每個方法,進入兩個if判斷,這個判斷就是判斷是不是需要依賴注入的方法,也就是上面說的條件就在這個體現。
假設是需要依賴注入的方法,接下來看看如何獲得需要被注入的物件,也就是方法的引數。
如果你的介面實現了ExtensionAccessorAware介面,那麼會注入給你的bean一個 ExtensionDirector ,ExtensionDirector 可以想象成是ExtensionLoader工廠,可以獲取每個介面的ExtensionLoader。