Java SPI 思想分析:
1. 當我們的系統裏面抽象的各個模塊,往往有很多不同的實現方案,比如日誌處理模塊、xml解析模塊、過濾器的模塊等,一般我們模塊之間是基於接口編程的,模塊之間不會對具體實現類進行硬編碼。一旦代碼裏涉及到具體實現類時,就違反了可插拔的原則,如果需要替換一種實現,就需要修改代碼。爲了實現在模塊裝配的時候能不在程序裏動態指明,這就需要一種服務發現機制。Java SPI 就是提供了這樣一種機制:爲某個接口尋找服務實現的機制。
2. spi規範約定:
當服務的提供者,提供了服務接口的一種實現之後,在jar包的META-INF/services/目錄裏同時創建一個以服務接口命名的文件。該文 件裏就是實現該服務接口的具體實現類。而當外部程序裝配這個
模塊的時候,就能通過該jar包META-INF/services/裏的配置文件找到具體的 實現類名,並裝載實例化,完成模塊的注入。 基於這樣一個約定就能很好的找到服務接口的實現類,而不需要再代碼裏制定。jdk提供服務實現查找的一個工具類:java.util.ServiceLoader
3. 使用場景: jdbc、dubbo
示例demo:
package cn.rhb.pojo;
public interface Service {
void say();
void getName(String name);
}
package cn.rhb.pojo;
/**
* @ClassName ServiceImpl1
* @Description 實現類1
* @Author rhb
* @Date 2020-06-19 10:26
* @Version 1.0
*/
public class ServiceImpl1 implements Service {
@Override
public void say() {
System.out.println("ServiceImpl1 Hello!");
}
@Override
public void getName(String name) {
System.out.println("1:"+name);
}
}
package cn.rhb.pojo;
/**
* @ClassName ServiceImpl2
* @Description 實現類2
* @Author rhb
* @Date 2020-06-19 10:26
* @Version 1.0
*/
public class ServiceImpl2 implements Service {
@Override
public void say() {
System.out.println("ServiceImpl2 Hello!");
}
@Override
public void getName(String name) {
System.out.println("2:"+name);
}
}
創建:resource/META-INF/services/cn.rhb.pojo.Service文件。文件內容:目標實現類完成路徑
cn.rhb.pojo.ServiceImpl1
注:JDBC中SPI的使用