Java SPI 機制
- 約定
- 可對接口、抽象類、普通類進行擴展;
- 所有擴展位於:classpath:/META-INF/services/$className文件中,
其中$className是被擴展 接口/抽象類/普通類 的全路徑名;- 文件中每行爲一個擴展類的全路徑名,多行代表有多個擴展類;
- 擴展加載機制
public static <S> ServiceLoader<S> load(Class<S> service)
public static <S> ServiceLoader<S> load(Class<S> service, ClassLoader loader)
- 優點
- Java原生支持,使用簡單便捷;
- 缺點
- 只能加載並實例化所有擴展,無法只加載指定擴展,存在潛在性能浪費。
Dubbo SPI 機制
是對Java SPI機制的模仿和增強實現。
- 約定
- 僅支持對接口的擴展,不支持對抽象類和普通類的擴展;
- 擴展可位於:
classpath:/META-INF/dubbo/internal/$interfaceName,
classpath:/META-INF/dubbo/$interfaceName,
classpath:/META-INF/services/$interfaceName,
文件中;- 文件中每一行是一個K=V對,K爲擴展名稱,V爲擴展的全路徑名;
- 不同擴展在不同的行,用不同的擴展名進行區分;
- 註解:
- @SPI:標註在被擴展接口的接口類型上;
- @Adaptive:該註解作用在一個類上,說明這個類是一個裝飾類;作用在接口方法上,Dubbo將爲接口生成一個動態代理類。
- @Activate: 標註在類或者方法上,滿足條件則自動激活一個擴展 。
- 擴展加載機制
類:ExtensionLoader,方法:
public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type)
public T getExtension(String name)
public T getAdaptiveExtension()
- 優點
- 支持按名稱加載指定擴展;
- 支持運行時自適應擴展加載機制;
- 支持運行時自動激活擴展加載機制;
- 缺點
- 沒感覺有什麼缺點,如果非要吹毛求疵的話,就是比較複雜吧。
Spring SPI 機制
- 約定
- 可對接口、抽象類、普通類進行擴展;
- 所有擴展位於:META-INF/spring.factories文件中,
- 文件中每一行是一個K=V對,K爲一個字符串標識,通常具有一定的含義,例如接口全路徑名稱或者註解的全路徑名稱,V爲擴展的全路徑名;
- 多個擴展支持逗號分隔,支持使用“\”換行;
- 擴展加載機制
類:SpringFactoriesLoader,方法:
public static <T> List<T> loadFactories(Class<T> factoryType, @Nullable ClassLoader classLoader)
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader)
- spring.factories文件格式符合Java的Properties屬性配置文件;
- 優點
- 支持按名稱加載指定擴展機制;
- 支持同一個擴展名稱多擴展機制;
- 配置文件支持多行配置機制;
- 支持@ConditionalOnClass按條件加載擴展;
- 缺點
- 歡迎補充。