Java的SPI机制
一、什么是SPI机制?
Java SPI(Service Provider Interface)是JDK内置的一种服务发现机制。它允许在运行时,动态地为接口寻找到其具体的实现类,从而实现模块间的解耦和可插拔的扩展能力。
二、SPI和API有啥区别?
- API (Application Programming Interface) :是服务提供方定义并实现的接口,供调用方使用。例如,你引入一个日期工具库,调用它的
format()方法,这就是在使用API。 - SPI (Service Provider Interface) :是服务调用方 (通常是框架)定义的接口标准,由服务提供方 (第三方开发者)来实现。例如,JDBC定义了
java.sql.Driver接口,而MySQL、PostgreSQL等数据库厂商提供各自的实现。
三、SPI的工作原理
SPI机制主要由三部分组成,遵循“ 约定优于配置 ”的原则:
- 服务接口(Service Interface) :由调用方定义的一组功能规范。
- 服务提供者(Service Provider) :对服务接口的具体实现。
- 服务加载器 (Service Loader) :核心类
java.util.ServiceLoader,负责在运行时发现和加载所有可用的服务提供者。
其工作流程如下:
- 提供服务 :服务提供者需要在JAR包的
META-INF/services/目录下,创建一个以服务接口全限定名命名的文件。文件内容是该接口的具体实现类的全限定名 。 - 加载服务 :服务调用方通过
ServiceLoader.load(接口名.class)方法,加载所有可用的服务实现。 - 使用服务 :遍历
ServiceLoader,即可获取并使用所有服务实现类的实例。
四、实战演示
首先,创建一个 spi-interface模块用于定义服务接口:
package com.hzp.spi;
/**
* 定义服务接口
*/
public interface Logger {
void log(String message);
}
第二步,创建 spi-provider模块用于实现上述接口(注意在pom内引入上面的依赖)
package com.hzp.provider;
import com.hzp.spi.Logger;
public class ConsoleLogger implements Logger {
@Override
public void log(String message) {
System.out.println("Console Logger: " + message);
}
}
第三步,在 resources目录下新建 META-INF/services目录,并在该目录新增以服务接口全限定名命名的文件(com.hzp.spi.Logger),文件内容为实现类的全限定类名:
com.hzp.provider.ConsoleLogger

最后是进行测试:
import com.hzp.spi.Logger;
import java.util.ServiceLoader;
public class Main {
public static void main(String[] args) {
ServiceLoader<Logger> loader = ServiceLoader.load(Logger.class);
for (Logger logger : loader) {
logger.log("Hello SPI!");
}
}
}
输出结果:
Console Logger: Hello SPI!
五、典型应用场景
SPI机制在Java生态中应用广泛,是许多框架实现扩展性的基石。
- JDBC (Java Database Connectivity) :这是SPI最经典的例子。只需将数据库驱动JAR包放入类路径,JDBC的
DriverManager就能通过SPI自动加载驱动,无需再使用Class.forName()手动注册。 - 日志门面 (SLF4J) :SLF4J定义日志接口,而Logback、Log4j2等是具体实现。运行时,SLF4J通过SPI自动绑定一个可用的日志实现。
- Spring Boot :Spring Boot的自动装配机制大量运用了SPI思想,通过加载
META-INF/spring.factories文件中的配置来实现组件的自动配置。 - Dubbo :Dubbo对原生SPI进行了扩展,使其功能更强大,这是其实现高度可扩展架构的基础。

浙公网安备 33010602011771号