Spring Boot SPI 用法教程
作者:Rysxt
一 概念与版本差异
- SPI(Service Provider Interface)是一种在运行时发现并加载服务实现的机制,核心是“接口与实现分离”。在 JDK 中通过 META-INF/services/接口全限定名 文件与 ServiceLoader 实现;在 Spring Boot 中扩展了该思想,使用 META-INF/spring.factories 与 SpringFactoriesLoader 来批量加载自动配置、监听器等扩展点。自 Spring Boot 2.7 起,官方为自动配置新增了 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件以替代 spring.factories 的自动配置注册方式,二者可并存(老项目仍可用 spring.factories)。Spring 的 SPI 加载机制与 IoC 容器深度集成,支持按条件加载与更灵活的实例化策略。
二 两种 SPI 用法速览
- 原生 Java SPI
- 约定路径:META-INF/services/接口全限定名;内容为每行一个实现类全限定名。
- 加载方式:ServiceLoader.load(接口.class),迭代器按需实例化实现类(延迟加载、默认无参构造)。
- 适用:与容器无关、轻量插件发现。
- Spring Boot SPI
- 约定路径与方式:
- 自动配置:Spring Boot 2.7+ 使用 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports(每行一个自动配置类);2.7 之前使用 META-INF/spring.factories 的 org.springframework.boot.autoconfigure.EnableAutoConfiguration 键。
- 其他扩展点:在 META-INF/spring.factories 中以键值对注册(如 ApplicationListener、自定义扩展接口)。
- 加载方式:SpringFactoriesLoader.loadFactories/loadFactoryNames 读取并实例化,可与 Spring 条件注解、环境集成。
三 实战一 自定义 Starter 并启用自动配置(Spring Boot 2.7+)
步骤
- 新建模块(如 my-spi-starter),无需启动类;添加依赖:
- spring-boot-autoconfigure
- (可选)spring-boot-configuration-processor(生成配置元数据)
- 定义业务接口与实现:
- 接口:com.example.spi.GreetingService
- 实现:com.example.spi.impl.EnglishGreetingService、ChineseGreetingService
- 编写自动配置类:
- 路径:com.example.spi.config.GreetingAutoConfiguration
- 要点:使用 @Configuration、条件注解(如 @ConditionalOnClass)、以及 @ConditionalOnMissingBean 保证用户可覆盖默认 Bean。
- 注册自动配置:在 resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 写入自动配置类全限定名(每行一个)。
- 使用:在业务项目中引入 starter 依赖,按类型注入 GreetingService 即可使用(若用户自行定义了同类型 Bean,则以用户 Bean 为准)。
关键文件示例
AutoConfiguration.imports
com.example.spi.config.GreetingAutoConfiguration
GreetingAutoConfiguration.java
@Configuration
@ConditionalOnClass(GreetingService.class)
public class GreetingAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public GreetingService greetingService() {
// 可按条件选择默认实现,或返回抽象工厂
return new EnglishGreetingService();
}
}说明
若需兼容 Spring Boot <2.7,可在同模块 resources/META-INF/spring.factories 增加:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.example.spi.config.GreetingAutoConfiguration
条件注解(如 @ConditionalOnClass/@ConditionalOnMissingBean)是编写自动配置的最佳实践,可避免冲突并提升可覆盖性。
四 实战二 使用 Java SPI 插件机制
步骤
定义插件接口:com.example.spi.Plugin
多个实现:com.example.spi.impl.PluginA、PluginB
注册插件:在 resources/META-INF/services/com.example.spi.Plugin 写入实现类全限定名(每行一个)。
加载插件(可在任意 Spring Bean 中):
import java.util.ServiceLoader;
ServiceLoader<Plugin> loader = ServiceLoader.load(Plugin.class);
for (Plugin p : loader) {
p.execute();
}适用场景
与 Spring 容器解耦的纯发现机制;若需要依赖注入、AOP、条件控制,优先考虑 Spring Boot 的 SpringFactoriesLoader 或在自动配置中封装 [ServiceLoader]。
五 常见问题与最佳实践
版本与路径
Spring Boot 2.7+ 推荐将自动配置写入 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports;老项目或第三方库仍可能使用 META-INF/spring.factories,注意维护兼容性。
条件装配
在自动配置类上使用 @ConditionalOnClass/@ConditionalOnMissingBean 等,明确生效条件与可覆盖性,避免与用户配置冲突。
避免类路径冲突
明确依赖版本与导出包,防止不同 JAR 提供同名实现导致不可预期行为。
扩展点选择
启动生命周期、环境处理等框架扩展点可用 spring.factories 注册(如 SpringApplicationRunListener、EnvironmentPostProcessor);业务插件发现可用 Java SPI 或 SpringFactoriesLoader。
可维护性与文档
为自定义 Starter 提供清晰的 README、配置示例与可覆盖策略说明,便于团队接入与二次开发。
到此这篇关于Spring Boot SPI 用法教程的文章就介绍到这了,更多相关Spring Boot SPI内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
