自动装配与 imports
This content is not available in your language yet.
自动装配把“类路径上可能需要的配置”变成候选集合,再交给条件系统决定是否真正注册 Bean。
先给答案:自动配置是“候选配置 + 条件筛选”,不是无条件替用户创建所有 Bean
Section titled “先给答案:自动配置是“候选配置 + 条件筛选”,不是无条件替用户创建所有 Bean”Boot 先从 imports 文件获得候选自动配置类,再通过条件判断决定哪些配置可以进入容器。候选与生效是两个阶段:一个 starter 提供候选,classpath、属性、Bean 是否存在和 Web 环境共同决定最终结果。
使用 imports 文件能把候选列表变成可索引、可排序、可诊断的元数据,而不是运行时扫描整个 classpath。排查自动配置时,应该依次看候选是否加载、条件是否匹配、用户 Bean 是否触发 @ConditionalOnMissingBean 的回退,以及最终 Bean 是否在 refresh 时创建。
@EnableAutoConfiguration │ ▼AutoConfigurationImportSelector#selectImports ├─► getCandidateConfigurations ├─► getExclusions ├─► fire import event └─► AutoConfigurationGroup.selectImports └─► sort + return configuration namesAutoConfigurationImportSelector在core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java:78实现DeferredImportSelector。selectImports()在:119取得自动配置入口。- 候选配置由
getCandidateConfigurations()在:200读取META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports。 - 排除集合由
getExclusions()在:247处理,非法排除在:230被校验。 - 分组器
AutoConfigurationGroup在:431,先在process():467收集配置,再在selectImports():489排序。 - 排序前移除全局排除项,关键逻辑在
:501。 - 测试中的 imports 文件位于
core/spring-boot-autoconfigure/src/test/resources/META-INF/spring/...AutoConfiguration.imports。 - 自动配置不会等价于无条件导入,最终是否生效仍取决于
@Conditional。
为什么使用 imports 文件
Section titled “为什么使用 imports 文件”替代方案:扫描所有包中的 @Configuration 类。
为什么不行:启动时扫描范围大、候选边界不稳定,还会把不应暴露的内部配置带入容器。
证据:候选发现集中在 getCandidateConfigurations(),由模块显式声明入口,再由条件和排序完成决策。
| 场景 | 现象 | 原因 | 规避 |
|---|---|---|---|
| 配置类未写入 imports | 自动配置完全不出现 | 候选发现阶段没有名字 | 检查资源路径和构建产物 |
| 自动配置顺序错误 | Bean 定义覆盖或缺失 | 依赖配置尚未先注册 | 使用 Boot 的 before/after 排序语义 |
| 排除类名错误 | 启动失败或排除无效 | handleInvalidExcludes 校验失败 |
使用实际配置类全名 |
显式候选清单比全量扫描更适合插件系统:它控制边界,条件负责环境适配,排序负责依赖关系,三者职责清晰。
面试锚点
AutoConfiguration.imports与旧式spring.factories的职责差异是什么?- 自动配置为什么是 deferred import?
- 用户 Bean 如何阻止默认自动配置?