|
参考
https://juejin.cn/post/6844903605695152142
https://cloud.tencent.com/developer/article/1785056 简概
SPI接口的定义在调用方,在概念上更依赖调用方;组织上位于调用方所在的包中;实现位于独立的包中。
接口的实现类需要在classpath下的META-INF/services/目录里创建一个以服务接口命名的文件,文件的内容就是接口的实现类的全类名。
当其他的程序需要这个服务的时候,就可以通过查找这个jar包(一般都是以jar包做依赖)的META-INF/services/中的配置文件,配置文件中有接口的具体实现类名,可以根据这个类名进行加载实例化,就可以使用该服务了。JDK中查找服务实现的工具类是:java.util.ServiceLoader。
应用示例
项目结构

定义接口
package world.shuashua.api;
public interface Service {
void supportService();
}
定义实现类
package world.shuashua.impl;
import world.shuashua.api.Service;
public class ServiceImpl implements Service {
public void supportService() {
System.out.println("由实现类:ServiceImpl 提供服务");
}
}配置spi文件
在resources目录下新建 META-INF/services 目录,并且在这个目录下新建一个与上述接口的全限定名一致的文件:
注意:这个META-INF/services 目录是写死的约定,在 java.util.ServiceLoader 源码实现中, java.util.ServiceLoader#PREFIX 可以看到这个目录的硬编码。

使用ServiceLoader进行加载
package world.shuashua;
import world.shuashua.api.Service;
import java.util.ServiceLoader;
public class ServiceLoad {
public static void main(String[] args) {
ServiceLoader<Service> load = ServiceLoader.load(Service.class);
load.forEach((service -> { // 因为实现了Iterable接口,所以有forEach方法
service.supportService();
System.out.println(service);
}));
}
}
原理
待补充
相关问题
- SPI重复加载时会创建多个实例吗?
会的。可以简单测试一下,使用spi加载两次就知道了。
|
|