当前位置: 首页 > news >正文

Spring 源码系列(21): 自动配置原理与 AutoConfigurationImportSelector

📌 阅读前提示:第 20 篇知道@EnableAutoConfigurationAutoConfigurationImportSelector批量导入配置类。本篇把这个「发动机」拆开——它从哪读配置、如何按条件过滤、如何排序,以及你的@Bean为什么能覆盖自动配置。这是 Boot 面试的「压轴题」。


一、引子:自动配置到底「自动」在哪

你没写DataSource、没写DispatcherServlet,但引入spring-boot-starter-web它们就出现了。秘密在于:AutoConfigurationImportSelector在容器启动的invokeBeanFactoryPostProcessors阶段(第 5 篇第 5 步),把一批xxxAutoConfiguration类导入容器,而这些类用@Bean+@Conditional声明了默认组件。


二、源码追踪:Selector 如何选配置

2.1 入口:DeferredImportSelector 接口

AutoConfigurationImportSelector实现DeferredImportSelector,所以它的导入延迟到所有其他配置处理完之后——保证你的@Bean先注册,自动配置后评估(这是「用户配置优先」的基础)。

2.2 读取候选配置

// AutoConfigurationImportSelector.java@OverridepublicString[]selectImports(AnnotationMetadataannotationMetadata){if(!isEnabled(annotationMetadata))returnNO_IMPORTS;AutoConfigurationEntryautoConfigurationEntry=getAutoConfigurationEntry(annotationMetadata);returnStringUtils.toStringArray(autoConfigurationEntry.getConfigurations());}protectedAutoConfigurationEntrygetAutoConfigurationEntry(AnnotationMetadatametadata){// ① 从 META-INF/spring.factories(或 .imports)读取所有自动配置类名List<String>configurations=getCandidateConfigurations(metadata,attributes);// ② 去重configurations=removeDuplicates(configurations);// ③ 按 @AutoConfigureBefore/After/Order 排序configurations=sort(configurations,autoConfigurationMetadata);// ④ 按 exclude 属性、@Conditional 过滤configurations=filter(configurations,autoConfigurationMetadata);returnnewAutoConfigurationEntry(configurations,exclusions);}

2.3 配置从哪读(Boot 2.7 变化)

protectedList<String>getCandidateConfigurations(...){// 旧版:META-INF/spring.factories 的 EnableAutoConfiguration 键// 新版(Boot2.7+):META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.importsList<String>configurations=ImportCandidates.load(AutoConfiguration.class,getBeanClassLoader()).getCandidates();returnconfigurations;}

⚠️ 版本差异:Boot 2.7 起官方逐步废弃spring.factories的自动配置写法,改推AutoConfiguration.imports纯类名清单;但 2.7 仍兼容spring.factories。Boot 3 则完全移除spring.factories自动配置。

2.4 @Conditional 过滤(条件评估)

filter最终落到ConditionEvaluator.shouldSkip,评估每个xxxAutoConfiguration上的条件注解:

  • @ConditionalOnClass:classpath 存在某类才生效
  • @ConditionalOnMissingBean:容器中还没有某 Bean 才生效(这就是你自定义@Bean能覆盖它的原因)
  • @ConditionalOnProperty:配置项匹配才生效
  • @ConditionalOnWebApplication:是 Web 应用才生效
@Configuration(proxyBeanMethods=false)@ConditionalOnClass({DataSource.class,EmbeddedDatabaseType.class})@ConditionalOnMissingBean(type="io.r2dbc.spi.ConnectionFactory")// 用户没配才用自动的@EnableConfigurationProperties(DataSourceProperties.class)publicclassDataSourceAutoConfiguration{...}

三、为什么你的 @Bean 能覆盖自动配置

核心机制 =DeferredImportSelector(延迟导入)+@ConditionalOnMissingBean

  1. 你的@Bean在普通配置阶段先注册;
  2. 自动配置类延迟导入,评估@ConditionalOnMissingBean时发现「用户已配,跳过」;
  3. 结果:用户 Bean 生效,自动配置退让。

📌 结论:Boot 的「约定优于配置」= 默认给你配好,但只要你显式声明同类型 Bean,就自动让位。这是最优雅的扩展点


四、自动配置加载与过滤流程图


五、常见误区

误区正解
自动配置类全部无条件注册错,经@Conditional过滤,多数按需生效
你的 @Bean 一定覆盖自动配置仅当自动配置类标了@ConditionalOnMissingBean同类型时
Boot 2.7 还用 spring.factories 自动配置兼容,但官方推荐迁移到AutoConfiguration.imports
DeferredImportSelector 没特殊作用它让自动配置延迟导入,保证用户 Bean 优先
自动配置类在 refresh 之前就生效invokeBeanFactoryPostProcessors阶段(第5步)导入,属容器启动中

🧪 面试题自测

  1. AutoConfigurationImportSelector从哪读自动配置类?
  2. Boot 2.7 的配置清单文件与旧版spring.factories有何不同?
  3. 自动配置类如何按条件过滤?列举 4 个@Conditional
  4. 为什么用户的@Bean能覆盖自动配置?
  5. DeferredImportSelector的作用?
  6. 自动配置类上常见的@ConditionalOnMissingBean解决了什么问题?

🔧 Debug 小技巧

AutoConfigurationImportSelector.filter断点,观察configurations列表从「几百个候选」被过滤到「实际生效的几十个」;再在OnBeanCondition.getMatchOutcome断点,看@ConditionalOnMissingBean如何判定你的 Bean 已存在而跳过自动配置。


下一篇预告

第 22 篇:条件注解@Conditional全家桶——@ConditionalOnClass/@ConditionalOnMissingBean/@ConditionalOnProperty等的底层Condition实现,以及如何自定义条件注解。


如果这篇对你有帮助,欢迎点赞 · 收藏 · 关注三连支持。

Spring 源码系列共 30 篇,由浅入深持续更新中。有疑问或想深挖的源码点,评论区告诉我,下篇见。

http://www.jsqmd.com/news/1405153/

相关文章:

  • 大客户销售落地工具多工具实测
  • 完整网页截图不用再手动拼图:免费开源Chrome扩展实测整页捕获
  • 辛集市|2026年河北省辛集市电大中专怎么报名?联系方式是多少?正规报名渠道查询 - 我叫小周
  • 光伏用户必看:ha-emporia-vue 太阳能反相设置(solar_invert)终极指南
  • 告别内卷内耗!2026巴厘岛小众解压攻略,程序员专属治愈之旅
  • Wand-Enhancer三步解锁专业版:免费游戏修改还能远程操控
  • 厘米级定位的秘诀:OpenMower如何融合RTK GPS与卡尔曼滤波实现精准导航
  • 三步开启中兴光猫工厂模式:zteOnu 完整实战指南
  • 商丘中医妙招:轻松缓解下肢动脉硬化问题
  • Adobe Downloader实测:macOS上3分钟搞定Adobe全家桶下载与安装
  • 2026年国内大理石平台选购指南 适配多类检测加工场景 - 滚动商讯
  • Policy Plus 使用完整指南:为所有 Windows 版本解锁组策略编辑器
  • IntelliJ IDEA 性能优化入门:一次大型项目卡顿问题的排查与修复记录
  • 网盘直链下载助手怎么用?从安装到进阶的3步完整指南
  • [Python]递归三部曲:线段树与滑动窗口最大值(19-21题全解析)
  • 2026 延津中原文武学校招生简章|招生政策、学费、升学率、报名须知梳理 - Luckyone王
  • 科学研究的类型
  • 活动签到流程怎么优化?低成本私有化方案真的好用吗?
  • Unity接入IAP内购(Android,IOS)最新流程,第三篇 后台对购买结果的验证以及发货(Android)
  • 计算机毕业设计LangChain智能体工作流编排-图检索增强(GraphRAG)-桥梁规范与巡检报告智能问答系统-知识图谱(Neo4j)和大模型(LLM)
  • whisper.cpp 语音转文字完全指南:从命令行安装到高级转录技巧
  • GitHub Desktop汉化终极指南:三分钟让整个客户端界面变中文
  • 网盘直链下载助手实测:告别限速焦虑,8大网盘真实链接一步到位
  • 条件变量condition_variable
  • Mate Engine 桌面伴侣完整上手指南:从零开始打造会聊天、能跳舞的 VRM 虚拟伙伴
  • 一条命令搞定中兴光猫:zteOnu 工厂模式与永久 Telnet 完整上手指南
  • 广州换季清理家中闲置奢包,爱马仕香奈儿 LV 迪奥,奢二网线下门店帮你评估包包价值 - 每日小知识
  • 微信聊天记录永久保存方案:WeChatExporter开源导出工具完整上手指南(含避坑清单)
  • 一文搞懂位图转矢量:vectorizer 让 PNG/JPG 秒变可无限放大的 SVG
  • Nucleus Co-op:让PC单机游戏秒变本地分屏神器的开源利器