【Java基础】SPI机制
2025/12/24...大约 4 分钟
【Java基础】SPI机制
什么是SPI?
SPI(Service Provider Interface)是Java提供的一种服务发现机制。它定义了一套接口规范,允许第三方提供具体实现,并通过标准方式让框架在运行时自动发现和加载这些实现。
API:框架定义,别人调用,框架提供接口和实现,调用方直接使用。
SPI:框架定义,别人实现,框架只定义接口规范,实现由第三方提供,框架在运行时动态发现和加载这些实现。
本质区别:API关注如何使用,SPI关注如何扩展。
核心思想:接口与实现分离 + 运行时动态发现。
设计模式视角:
- 策略模式:不同实现代表不同的策略
- 工厂模式:ServiceLoader作为统一工厂
- 插件模式:实现类作为可插拔插件
工作机制流程:
[SPI接口定义]
↑
[实现类1] [实现类2] [实现类3]
↑
[META-INF/services/接口全限定名 文件]
↑
[ServiceLoader加载机制]
↑
[应用程序使用]典型应用:
- JDBC驱动:Java定义数据库连接接口,MySQL/Oracle等厂商提供实现
- 日志框架:SLF4J定义接口,Logback/Log4j提供实现
- 支付网关:定义支付接口,微信/支付宝提供具体实现
SPI使用步骤
1. 定义服务接口
// 在项目A中定义接口
public interface PaymentService {
boolean pay(BigDecimal amount);
String getPaymentType();
}2. 实现服务接口
// 项目B:微信支付实现
public class WechatPayService implements PaymentService {
// 具体实现...
}
// 项目C:支付宝支付实现
public class AlipayService implements PaymentService {
// 具体实现...
}3. 配置SPI文件
位置:src/main/resources/META-INF/services/
文件名:接口全限定名(如com.example.PaymentService)
内容:实现类全限定名(每行一个)4. 使用ServiceLoader加载
// 在项目D(使用方)中加载
ServiceLoader<PaymentService> loader =
ServiceLoader.load(PaymentService.class);
for (PaymentService service : loader) {
System.out.println("发现支付方式:" + service.getPaymentType());
}项目架构示例
【项目结构】
├── 【项目A】支付规范(接口定义)
│ ├── payment-api(接口模块)- 定义PaymentService接口
│ └── payment-core(核心模块)- SPI加载器与工厂类
│
├── 【项目B】微信支付实现
│ ├── WechatPayServiceImpl(具体实现)
│ └── META-INF/services/配置
│
├── 【项目C】支付宝支付实现
│ ├── AlipayServiceImpl(具体实现)
│ └── META-INF/services/配置
│
└── 【项目D】业务应用(使用方)
├── 依赖:payment-core + 具体实现jar包
└── 通过PaymentFactory统一调用【依赖关系】
- 项目B、C依赖项目A的接口模块(payment-api)
- 项目D依赖项目A的核心模块(payment-core)
- 项目D可选依赖项目B、C的实现jar包
SPI的优缺点
优点:
- 解耦性强:接口定义与实现完全分离
- 扩展方便:新增实现只需添加jar包和配置文件,无需修改原有代码
- 动态发现:运行时自动加载所有可用实现
- 标准化:Java原生支持,约定明确
缺点:
- 全量加载:会加载所有实现类,不能按需加载
- 缺乏IoC支持:需要手动管理实例创建和依赖注入
- 每次创建新实例:ServiceLoader每次遍历都会创建新对象,不保证单例
- 配置方式固定:必须严格遵循META-INF/services/目录结构
Spring Boot对SPI的增强
Spring Boot在Java标准SPI基础上进行了重要改进:
【对比表】
| 特性 | Java标准SPI | Spring Boot SPI |
|---|---|---|
| 配置文件 | META-INF/services/接口名 | META-INF/spring.factories |
| 配置格式 | 每行一个实现类 | Key=Value格式,支持多行 |
| 加载内容 | 接口实现类 | 自动配置类、监听器、初始化器等 |
| 核心类 | ServiceLoader | SpringFactoriesLoader |
【Spring Boot自动装配原理】
// @SpringBootApplication → @EnableAutoConfiguration
// → AutoConfigurationImportSelector
// → SpringFactoriesLoader.loadFactoryNames()
// → 读取META-INF/spring.factories
// → 加载所有自动配置类【spring.factories文件示例】
# 支持多种类型的扩展
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.MyAutoConfiguration,\
com.example.DataSourceAutoConfiguration
org.springframework.context.ApplicationListener=\
com.example.MyEventListener
org.springframework.boot.SpringApplicationRunListener=\
com.example.MyRunListener总结要点
- SPI核心:接口定义规范,实现由第三方提供,运行时自动发现
- 实现方式:META-INF/services/ + ServiceLoader
- 设计思想:面向接口编程,实现可插拔架构
- 应用场景:驱动扩展、插件系统、框架扩展点
- Spring增强:扩展为spring.factories,支持更多扩展点,成为自动装配基石