简单来说:
Api,你调用框架
spi,框架调用你
一、先记住这四个角色
可以先记住这四个角色:
- Java SPI:JDK 级插件发现(最原始)
- Spring Boot SPI:框架级插件发现(带生命周期)
- 自动装配:框架替你做“默认决策”
- 显式装配:你明确告诉 Spring “我要什么”
后面所有细节,都是这四件事的不同组合。
二、Java SPI 注入(JDK 原生)
1️⃣ Java SPI 是什么角色?
一句话:
Java SPI 只负责“发现实现”,不负责“何时加载、是否加载、如何使用”。
2️⃣ Java SPI 的组成
(1)接口(扩展点)
public interface PayService { void pay(); }(2)实现类
public class AliPayService implements PayService { }(3)配置方式(唯一)
📍META-INF/services/接口全限定名
META-INF/services/com.example.PayService内容:
com.example.AliPayService3️⃣ 谁来“注入”?——必须你自己写
ServiceLoader<PayService> loader = ServiceLoader.load(PayService.class);这是 Java SPI 的生效开关。
没有这行代码:
- 不扫描
- 不实例化
- 不注入
4️⃣ Java SPI 的本质特征
维度 | Java SPI |
配置是否自动生效 | ❌ 否 |
是否需要触发代码 | ✅ 必须 |
生命周期 | ❌ 无 |
条件装配 | ❌ 无 |
使用场景 | 基础库、JDK 扩展 |
关键词:拉模型(Pull)
三、Spring Boot SPI 注入(框架级)
Spring SPI 的本质是:
Spring 在启动过程中,主动帮你调用“ServiceLoader 类似的逻辑”。
你只需要“登记”,不用“触发”。
四、Spring Boot SPI 的几种主要形式(按层级)
第一类:自动配置 SPI(最重要)
1️⃣ 配置方式(新一代,推荐)
📍META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
com.example.MyAutoConfiguration2️⃣ Java 类
@AutoConfiguration public class MyAutoConfiguration { @Bean public MyService myService() { ... } }3️⃣ 特点
特性 | 说明 |
是否自动生效 | ✅ |
是否进 IoC | ✅ |
是否可条件控制 | ✅ |
是否需 @Import | ❌ |
面向对象 | starter / 框架作者 |
第二类:传统 Spring SPI(仍在使用)
📍META-INF/spring.factories
org.springframework.context.ApplicationListener=\ com.example.MyListener常见接口:
ApplicationListenerApplicationContextInitializerEnvironmentPostProcessor
特点:
- 启动非常早
- 多数不进入 IoC
- 仍属于框架级扩展机制
第三类:IoC 内部扩展(不是 SPI,但常混)
BeanFactoryPostProcessorBeanPostProcessorImportSelector
这些是:
容器内部扩展,而不是 classpath 级插件机制
五、什么是“自动装配”?
一句话定义(非常重要)
Spring Boot 根据环境和条件,自动决定“要不要装某些 Bean”。
自动装配 = 自动配置类 + 条件判断。
自动装配的典型特征
- 配置类来自 SPI(imports / spring.factories)
- 几乎都有
@Conditional - 默认生效,但允许你覆盖
自动装配 ≠ 自动扫描
自动扫描是:
@ComponentScan自动装配是:
@ConditionalOnClass @ConditionalOnMissingBean决策权在框架,不在你。
六、什么是“显式装配”?
一句话定义
开发者明确告诉 Spring:这个 Bean / 配置我要。
常见显式装配方式
方式 | 示例 |
| 手动定义 |
| 明确配置 |
| 主动引入 |
XML | 老派但明确 |
显式装配的哲学
- 开发者掌控
- 行为可预测
- 不“猜”
七、自动装配 vs 显式装配(对照表)
维度 | 自动装配 | 显式装配 |
谁做决定 | Spring Boot | 开发者 |
是否默认生效 | 是 | 否 |
是否可覆盖 | 是 | 本来就是你写的 |
典型注解 |
|
|
适用场景 | 通用能力 | 业务逻辑 |
八、工程级总结
- Java SPI:实现发现,但使用者负责一切
META-INF/services/com.example.PayService
这是java的spi注入,需要自己写ServiceLoader
- Spring Boot SPI:框架级实现发现 + 生命周期管理
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
这是springBoot的新型自动装配方式
META-INF/spring.factories
传统 Spring SPI(仍在使用)
- 自动装配:框架提供默认能力,用户可覆盖
- 显式装配:业务代码直接做决定
选择哪种方式,本质取决于:
决策权应该在框架,还是在业务代码。