一.定義 SPI(Service Provider Interface) 是一種面向介面編程的技術,它可以讓一個程式根據介面約定規範自動發現和載入對應的實現類。它是一種 Java 種的介面編程規範,它定義了介面和服務提供者之間的約定規範,使得在運行時動態載入實現該介面的類。SPI 機制是通過在服務提 ...
一.定義
SPI(Service Provider Interface) 是一種面向介面編程的技術,它可以讓一個程式根據介面約定規範自動發現和載入對應的實現類。它是一種 Java 種的介面編程規範,它定義了介面和服務提供者之間的約定規範,使得在運行時動態載入實現該介面的類。SPI 機制是通過在服務提供者介面上定義註解和在配置文件種指定實現類的方式來實現的。
### 優點: SPI 核心思想就是解耦。我只定義標準,具體實現由不同的廠商實現。
### 缺點: 不能按需載入,必須遍歷所有實現並初始化,但是有點初始化可能會很耗時 、獲取某個實現類的方式不夠靈活,只能遍歷獲取 、多線程使用 ServiceLoader 不安全
二.實現流程
當服務的提供者提供了一種介面的實現之後,需要在 classpath 下的 META-INF/services/ 目錄里創建一個以服務介面命名的文件,這個文件里的內容就是這個介面的具體實現類。當其他程式需要這個服務的時候,就會找到這個類並且實例化。JDK 中查找服務的實現的工具類是:java.util.ServiceLoader。
三.簡單demo實現
一.定義介面。創建兩個實現類
public interface Plugin {
void execute();
}
public class PluginA implements Plugin {
@Override
public void execute() {
System.out.println("PluginA.execute is done");
}
}
public class PluginB implements Plugin {
@Override
public void execute() {
System.out.println("PluginB.execute is done");
}
}
二.classpath 下的 META-INF/services/下新建一個文件,文件名為Plugin的全路徑名,文件內容為PluginA和PluginB的全路徑名
三.模擬測試
public class PluginTest {
public static void main(String[] args) {
ServiceLoader<Plugin> serviceLoader=ServiceLoader.load(Plugin.class);
Iterator<Plugin> itre = serviceLoader.iterator();
while(itre.hasNext()){
//itre.next() 這行代碼會對 SPI 配置的實現類進行初始化
itre.next().execute();
}
}
}
//列印結果:
//PluginA.execute is done
//PluginB.execute is done