JAVA - SPI理解
先來看看我們平時使用的比較多的api:實現方提供了接口和實現,我們可以調用某些實現類的功能,實現方的接口和代碼通常會放在一個包中
那如果接口屬於調用方時,我們就稱爲其爲SPI,即一種爲某個接口尋找服務實現的一種機制,舉個簡單的例子,jdbc連接數據庫,第三方廠商根據一個統一的規範(jdbc.driver)實現各自的邏輯,所以當你使用jdbc的時候僅僅需要引入不同的第三方廠商的spi接口服務即可,Mysql的則是com.mysql.jdbc.Drive,Oracle則是oracle.jdbc.driver.OracleDriver。
spi的約定:
當服務的提供者,提供了服務接口的一種實現之後,在jar包的META-INF/services/目錄裏同時創建一個以服務接口命名的文件,該文件裏就是實現該服務接口的具體實現類。當外部程序裝配這個模塊的時候,就能通過該jar包META-INF/services/裏的配置文件找到具體的實現類名,並裝載實例化,完成模塊的注入。
基於這樣的一個約定,就能很好的找到服務接口的實現類,而不需要在代碼裏指定,jdk提供服務實現類查找的工具類:java.util.ServiceLoader
SPI 簡單示例:
- 項目結構
- spi-api 定義的接口,針對第三方廠商定義的統一規範,只有接口
- spi-doctor 接口實現,即第三方廠商針對接口的不同實現之一
- spi-teacher 接口實現,即第三方廠商針對接口的不同實現之一
- spi-core 提供給用戶使用的文件,用戶使用的時候引入對應廠商的jar即可
- api-spi
public interface PeopleAPI {
public void profession();
}
- spi-doctor
接口實現:
public class Doctor implements PeopleAPI {
public void profession() {
System.out.println("我是一名醫生");
}
}
在resource下新建目錄META-INF/services,新建文件:com.PeopleAPI 寫入具體的實現類名
com.test.Doctor
pom.xml
<dependencies>
<dependency>
<groupId>z</groupId>
<artifactId>spi-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
- spi-teacher
類似spi-doctor一樣的做法
public class Teacher implements PeopleAPI {
public void profession() {
System.out.println("我是一名老師");
}
}
META-INF/services/com.PeopleAPI
com.test.Teacher
pom.xml
<dependencies>
<dependency>
<groupId>z</groupId>
<artifactId>spi-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
- spi-core
public class PeopleCore {
public void getPeopleCore (){
ServiceLoader<PeopleAPI> serviceLoader = ServiceLoader.load(PeopleAPI.class);
Iterator<PeopleAPI> peoples = serviceLoader.iterator();
boolean flag = true;
while (peoples.hasNext()){
flag = false;
PeopleAPI peopleAPI = peoples.next();
peopleAPI.profession();
}
if(flag){
throw new RuntimeException("沒找到具體實現類");
}
}
}
pom.xml
<dependency>
<groupId>z</groupId>
<artifactId>spi-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>z</groupId>
<artifactId>spi-teacher</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- 想用哪個只需要替換就可-->
<!-- <dependency>-->
<!-- <groupId>z</groupId>-->
<!-- <artifactId>spi-doctor</artifactId>-->
<!-- <version>1.0-SNAPSHOT</version>-->
<!-- </dependency>-->
test
@Test
public void test1(){
PeopleCore peopleCore = new PeopleCore();
peopleCore.getPeopleCore();
}