SPI本质上提供了一种服务发现机制,通过某个接口来查找外部实现了该接口的服务,配合ServiceLoader等库,可以实现服务的自动装载,类似于Spring的IOC,本质上都是解耦,面向接口编程。
什么是spi
SPI(Service Provider Interface,服务提供接口) ,和Spring Boot中configuration.jar中的SpringFactoriesLoader使用方法很像。
怎么使用
- 当服务提供者提供了接口的一种具体实现后,在jar包的META-INF/services目录下创建一个以“接口全限定名”为命名的文件,内容为实现类的全限定名;
- 接口实现类所在的jar包放在主程序的classpath中;
- 主程序通过java.util.ServiceLoder动态装载实现模块,它通过扫描所有META-INF/services目录下的配置文件找到实现类的全限定名,把类加载到JVM;
- SPI的实现类必须有一个无参的构造方法;
实现
项目结构
代码
1.创建接口和实现类
public class DefaultLogger implements Logger {
@Override
public void printInfo() {
System.out.println("DefaultLogger");
}
}
//LogBack同上
2.在jar包的META-INF/services目录下创建一个以“接口全限定名”为命名的文件,内容为实现类的全限定名
cn.andy.spi.demo.impl.DefaultLogger
cn.andy.spi.demo.impl.LogBack
3.关键代码ServiceLoader.load(Class service)
ServiceLoader<Logger> load = ServiceLoader.load(Logger.class);
Iterator<Logger> iterator = load.iterator();
while (iterator.hasNext()){
Logger next = iterator.next();
next.printInfo();
}
运行结果,控制台打印出DefaultLogger,LogBack
使用场景
- 数据库驱动Driver加载
- SLF4J加载不同提供商的日志实现类
- Dubbo