配合 JavaPoet 食用更佳

SPI 全称为 (Service Provider Interface) ,是JDK内置的一种服务提供发现机制。

当服务的提供者,提供了服务接口的一种实现之后,在jar包的META-INF/services/目录里同时创建一个以服务接口命名的文件。该文件里就是实现该服务接口的具体实现类。而当外部程序装配这个模块的时候,就能通过该jar包META-INF/services/里的配置文件找到具体的实现类名,并装载实例化,完成模块的注入。 基于这样一个约定就能很好的找到服务接口的实现类,而不需要再代码里制定。

JDK提供服务实现查找的一个工具类:java.util.ServiceLoader

举个栗子🌰

定义一个接口

public interface IProvider {
    String getName();
}

定义实现类

public class ProviderA implements IProvider {
    @Override
    public String getName() {
        return "I'm ProviderA";
    }
}
public class ProviderB implements IProvider {
    @Override
    public String getName() {
        return "I'm ProviderB";
    }
}

src/main目录下创建resources/META-INF/services文件夹,在services下创建文件名是接口完整路径的文件pers.victor.test.IProvider,文件内写入实现类的完整路径,如果有多个实现类则一行写一个,文件内容如下

pers.victor.test.ProviderA
pers.victor.test.ProviderB

在代码里获取实现类实例

ServiceLoader<IProvider> serviceLoader = ServiceLoader.load(IProvider.class);
for (IProvider provider : serviceLoader) {
	 System.out.println(provider.getName());
}

打印结果

I'm ProviderA
I'm ProviderB

成功地利用接口获取了实现类。

如果工程内有AB模块不互相依赖但是想做一些调用之类的,SPI可以提供一种思路。

因为文件夹和文件的创建都是手动完成的,比较繁琐,这个时候可以和JavaPoet配合使用,在编译时创建文件夹和文件,省时省力。