1.简介
SPI(Service Provider Interface)服务提供者机制,主要便于服务发现和动态替换,SPI机制需要遵守如下规范
如Java就提供了一个标准接口 java.sql.Driver,各个数据库厂商可以实现这个接口,并提供jar包,开发者引入jar包后可以被应用程序加载。
2.使用规范
1).META-INF/services/ 目录
第三方实现需要在jar包中(classpath)的META-INF/services/
2).配置文件
目录下创建一个以服务接口命名的文件,如上图java.sql.Driver文本以接口为名,内容如下,是第三方的实现类全限定名
com.mysql.jdbc.Driver com.mysql.fabric.jdbc.FabricMySQLDriver
3).serviceLoader加载实现类
java.util.ServiceLoader 加载spi实现类,load(Driver.class)方法为给定的服务接口和类加载器创建新的服务加载器。
根据接口类加载实现类的过程,根据导入项目中的jar包中的特定路径META-INF/services/ 找到接口类为名的文本文件,即可得到实现类的全限定名,再用类加载器加载导入的jar包中类class文件。
3.Demo自实现
public interface HelloInterface {
void sayHello();
}
public class ImageHello implements HelloInterface{
@Override
public void sayHello() {
System.out.println("hello image");
}
}
public class TextHello implements HelloInterface {
@Override
public void sayHello() {
System.out.println("hello text");
}
}
public class SPIMain {
public static void main(String[] args) {
ServiceLoader<HelloInterface> hellos = ServiceLoader.load(HelloInterface.class);//加载实现类
if (hellos!=null) {
for (HelloInterface helloInterface: hellos) {
helloInterface.sayHello();
}
}
}
}
输出结果,由此可见,Main函数中并未直接指定实现类的全限定名,ServiceLoader会去配置文件中获取配置,找到实现类并加载,并生成实例。