仿照java的spi,dubbo實現自己的spi

1、平時遇到過的使用java的spi的例子

    1)mysql的驅動

        

2)spring-web

2、spi的設計目標

面向對象的設計裏,模塊之間是接口編程,模塊之間不對實現類進行硬編碼,如果實現類寫死在代碼裏,想要換一種實現,就需要修改代碼,爲了不在代碼裏寫死,就需要一種服務的發現機制,爲某個接口尋找服務實現的機制,有點類似ioc,將裝配的控制權移交到代碼之外

3、spi的約定

當一個接口有多個實現類的時候,一般在META-INF/services/目錄下,創建接口的同名文件(接口的包名+文件名)

文件的內容就是接口的實現類的名稱(包名+文件名)

而當外部程序裝配這個模塊的時候,就能通過該jar包META-INF/services/裏的配置文件找到具體的實現類名,並裝載實例化,完成模塊的注入。 基於這樣一個約定就能很好的找到服務接口的實現類,而不需要再代碼裏制定。jdk提供服務實現查找的一個工具類java.util.ServiceLoader

4、查找接口的實現通過ServiceLoader來完成

Iterator<UserService> services = ServiceLoader.load(UserService.class).iterator();

5、dubbo爲什麼要實現自己的spi,而不是用jdk的spi

    1)jdk的spi會一次性實例化一個擴展點的所有實現,初始化會很耗時間,並且沒有用到的實現也會加載,浪費資源

    2)增加了對擴展點ioc和aop的支持,一個擴展點可以直接setter注入其他擴展點

6、dubbo的spi的約定

dubbo spi 在JAVA自帶的SPI基礎上加入了擴展點的功能,即每個實現類都會對應至一個擴展點名稱,其目的是 應用可基於此名稱進行相應的裝配。這樣就解決了jdk加載全部的實現類的缺點了。

dubbo spi 目錄文件

dubbo spi  文件內容:

wanglu=wanglu.dubbo.server.WlFilter

裝配自定義Filter

<dubbo:provider filter="wanglu" timeout="2000" retries="2" id="abc"></dubbo:provider>

 

7、dubbo的spi的源碼解析

        1)dubbo spi的目的:dubbo獲取一個實現類的對象

        2)通過ExtensionLoader實現spi擴展點的加載

        途徑:public T getExtension(String name)

        實現途徑:

         getExtensionLoader(Class<T> type),作用就是爲該Class<T>接口new一個ExtensionLoader,然後緩存起來。

         getAdaptiveExtension()  獲取一個擴展裝飾類的對象,這個類有一個規則,如果他沒有@Adaptive註解,就動態創建一個裝飾類,例如:       Protocol$Adaptive對象

       getExtension(String name)獲取一個對象

    3)源碼

---------------------------------------------------ExtensionLoader.getExtensionLoader(Class<T> type)
ExtensionLoader.getExtensionLoader(Container.class)
-->this.type = type;
-->objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
   -->ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
      -->this.type = type;
      -->objectFactory = null;

執行以上的代碼,完成了兩個屬性的初始化
1、每個ExtensionLoader都包含兩個值type和objectFactory
    <T> type  //構造器初始化要得到的接口名
    ExtensionFactory objectFactory 構造器,初始化時AdaptiveExtensionFactory【SpiExtensionFactory】
2、new 一個ExtensionLoader都存儲在ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS
3、關於objectFactory的一些細節
    objectFactory 就是ExtensionFactory 通過ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()來實現的,但是objectFactory 爲空
    objectFactory就是dubbo的IOC提供所有對象的

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章