一、平時遇到過的使用java的spi的例子java
1)mysql的驅動mysql
2)spring-webweb
二、spi的設計目標spring
面向對象的設計裏,模塊之間是接口編程,模塊之間不對實現類進行硬編碼,若是實現類寫死在代碼裏,想要換一種實現,就須要修改代碼,爲了避免在代碼裏寫死,就須要一種服務的發現機制,爲某個接口尋找服務實現的機制,有點相似ioc,將裝配的控制權移交到代碼以外sql
三、spi的約定編程
當一個接口有多個實現類的時候,通常在META-INF/services/目錄下,建立接口的同名文件(接口的包名+文件名)緩存
文件的內容就是接口的實現類的名稱(包名+文件名)ide
而當外部程序裝配這個模塊的時候,就能經過該jar包META-INF/services/裏的配置文件找到具體的實現類名,並裝載實例化,完成模塊的注入。 基於這樣一個約定就能很好的找到服務接口的實現類,而不須要再代碼裏制定。jdk提供服務實現查找的一個工具類java.util.ServiceLoader工具
四、查找接口的實現經過ServiceLoader來完成this
Iterator<UserService> services = ServiceLoader.load(UserService.class).iterator();
五、dubbo爲何要實現本身的spi,而不是用jdk的spi
1)jdk的spi會一次性實例化一個擴展點的全部實現,初始化會很耗時間,而且沒有用到的實現也會加載,浪費資源
2)增長了對擴展點ioc和aop的支持,一個擴展點能夠直接setter注入其餘擴展點
六、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>
七、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;
執行以上的代碼,完成了兩個屬性的初始化 一、每一個ExtensionLoader都包含兩個值type和objectFactory <T> type //構造器初始化要獲得的接口名 ExtensionFactory objectFactory 構造器,初始化時AdaptiveExtensionFactory【SpiExtensionFactory】 二、new 一個ExtensionLoader都存儲在ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS 三、關於objectFactory的一些細節 objectFactory 就是ExtensionFactory 經過ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()來實現的,可是objectFactory 爲空 objectFactory就是dubbo的IOC提供全部對象的