Dubbo內核實現之SPI簡單介紹
JDK實現spi服務查找: ServiceLoader
首先定義下示例接口
package com.example;
public interface Spi {
booleanisSupport(String name);
String sayHello();
}
ServiceLoader會遍歷所有jar查找META-INF/services/com.example.Spi文件
package com.a.example;
public class SpiAImpl implements Spi {
publicboolean isSupport(String name) {
return"SPIA".equalsIgnoreCase(name.trim());
}
public String syaHello() {
return “hello 我是廠商A”;
}
}
在A廠商提供的jar包中的META-INF/services/com.example.Spi文件內容為:
com.a.example.SpiAImpl #廠商A的spi實現全路徑類名
B廠商提供實現
package com.b.example; public class SpiBImpl implements Spi { publicboolean isSupport(String name) { return"SPIB".equalsIgnoreCase(name.trim()); } public String syaHello() { return “hello 我是廠商B”; } }
在B廠商提供的jar包中的META-INF/services/com.example.Spi文件內容為:
com.b.example.SpiBImpl #廠商B的spi實現全路徑類名
ServiceLoader.load(Spi.class)讀取廠商A、B提供jar包中的文件,ServiceLoader實現了Iterable接口可通過while for循環語句遍歷出所有實現。
一個接口多種實現,就如策略模式一樣提供了策略的實現,但是沒有提供策略的選擇, 使用方可以根據isSupport方法根據業務傳入廠商名來選擇具體的廠商。
public class SpiFactory {
//讀取配置獲取所有實現
privatestatic ServiceLoader spiLoader = ServiceLoader.load(Spi.class);
//根據名字選取對應實現
publicstatic Spi getSpi(String name) {
for(Spi spi : spiLoader) {
if(spi.isSupport(name) ) {
returnspi;
}
}
returnnull;
}
}
SPI接口定義
定義了@SPI註解
public @interface SPI {
Stringvalue() default ""; //指定默認的擴展點
}
只有在接口打了@SPI註解的接口類才會去查找擴展點實現,會依次從這幾個文件中讀取擴展點
META-INF/dubbo/internal/ //dubbo內部實現的各種擴展都放在了這個目錄了
META-INF/dubbo/
META-INF/services/
我們以Protocol接口為例, 接口上打上SPI註解,默認擴展點名字為dubbo
@SPI("dubbo")
public interface Protocol{
}
具體實現的類有:
所以說:Remoting實現是Dubbo協議的實現。
Dubbo內核實現之SPI簡單介紹