如何实现SPI机制

发布时间 2023-12-11 19:40:35作者: 一直深夜吃食的喵

 一.定义

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