在Java領域,有一種重要的服務擴展機制,即SPI,它在編寫框架和項目應用中起着重要的作用。SPI的英文全稱爲service provider interface,即服務提供接口,在JDK、Spring和Dubbo中都有它的存在。
我個人認爲,SPI存在最根本的目的是實現模塊或組件的可插拔性,核心思想那便是解耦了。
一、JDK
在JDK的java.util包下有一個非常顯眼的類,即ServiceLoader。不妨打開該類的源碼,看到註釋的第一行是A simple service-provider loading facility,用我粗大的英語能力翻譯出大概意思是一個簡單的服務提供者加載工具。是的,你沒有看錯,這就是JDK中SPI機制的核心類。
使用JDK的SPI,需要遵循如下規則:
1、當服務提供方提供接口的具體實現後,在classpath下創建META-INF/services目錄。
2、再創建一個以接口全限定名命名的配置文件,將實現類的全類名寫入文件。
3、通過ServiceLoader加載模塊。
簡單示例:
首先定義一個接口
public interface Animal {
void sound();
}
接下來定義兩個實現類,分別是Dog和Cat
public class Dog implements Animal {
@Override
public void sound(){
System.out.println("汪汪汪的叫");
}
}
public class Cat implements Animal {
@Override
public void sound(){
System.out.println("喵喵喵的叫");
}
}
然後在classpath下創建META-INF/services目錄,創建文件以Animal的全類名命名,比如com.xxx.Animal,文件內寫入兩個實現類的全類名,如下:
com.xxx.Dog
com.xxx.Cat
最後編寫測試代碼
public class Test {
public static void main(String[] args) {
ServiceLoader<Animal> serviceLoader = ServiceLoader.load(Animal.class);
serviceLoader.forEach(Animal::sound);
}
}
測試結果如下
"C:\Program Files\Java\jdk1.8.0_191\bin\java.exe" "-javaagent:C:\Program
汪汪汪的叫
喵喵喵的叫
二、Spring和Dubbo
如果理解了JDK的SPI機制,那麼Spring和Dubbo中的SPI也就理解了,原理是一樣的,只是實現的方式有些許區別。
Spring中SPI的核心類:
Dubbo中SPI的核心類:
Spring、Dubbo 和JDK SPI實現的區別:
1、配置文件路徑不同
2、配置文件內容書寫方式不同
3、編碼方式不同