Spring Boot SPI 教程

​​​一 概念与版本差异​

  • ​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+)​

步骤

  1. 新建模块(如 ​my-spi-starter​ ),无需启动类;添加依赖:
    • ​spring-boot-autoconfigure​
    • (可选)​spring-boot-configuration-processor​(生成配置元数据)
  2. 定义业务接口与实现:
    • 接口:​com.example.spi.GreetingService​
    • 实现:​com.example.spi.impl.EnglishGreetingService​​ChineseGreetingService​
  3. 编写自动配置类:
    • 路径:​com.example.spi.config.GreetingAutoConfiguration​
    • 要点:使用 ​@Configuration​ 、条件注解(如 ​@ConditionalOnClass​ )、以及 ​@ConditionalOnMissingBean​ 保证用户可覆盖默认 Bean。
  4. 注册自动配置:在 ​resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports​ 写入自动配置类全限定名(每行一个)。
  5. 使用:在业务项目中引入 starter 依赖,按类型注入 ​GreetingService​ 即可使用(若用户自行定义了同类型 Bean,则以用户 Bean 为准)。

关键文件示例

  • AutoConfiguration.imports

    java 复制代码
    com.example.spi.config.GreetingAutoConfiguration
  • GreetingAutoConfiguration.java

    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​ 增加:

    java 复制代码
    org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
      com.example.spi.config.GreetingAutoConfiguration
  • 条件注解(如 ​@ConditionalOnClass/@ConditionalOnMissingBean​)是编写自动配置的最佳实践,可避免冲突并提升可覆盖性。

​四 实战二 使用 Java SPI 插件机制​

步骤

  1. 定义插件接口:​com.example.spi.Plugin​

  2. 多个实现:​com.example.spi.impl.PluginA​​PluginB​

  3. 注册插件:在 ​resources/META-INF/services/com.example.spi.Plugin​ 写入实现类全限定名(每行一个)。

  4. 加载插件(可在任意 Spring Bean 中):

    java 复制代码
    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​、配置示例与可覆盖策略说明,便于团队接入与二次开发。
相关推荐
@淡 定3 小时前
Redis热点Key独立集群实现方案
数据库·redis·缓存
野生的码农3 小时前
码农的妇产科实习记录
android·java·人工智能
laocooon5238578864 小时前
mysql,100个题目。
数据库·sql·mysql
Web极客码4 小时前
如何在Ubuntu服务器上安装和配置BIND9
服务器·数据库·ubuntu
W001hhh4 小时前
数据库实训Day004上午
数据库
毕设源码-赖学姐4 小时前
【开题答辩全过程】以 高校人才培养方案管理系统的设计与实现为例,包含答辩的问题和答案
java
funfan05175 小时前
【运维】MySQL数据库全量备份与恢复实战指南:从入门到精通
运维·数据库·mysql
+VX:Fegn08955 小时前
计算机毕业设计|基于springboot + vue在线音乐播放系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
一起努力啊~5 小时前
算法刷题-二分查找
java·数据结构·算法
小途软件5 小时前
高校宿舍访客预约管理平台开发
java·人工智能·pytorch·python·深度学习·语言模型