Spring Boot 自动装配不是魔法:@ConditionalOnMissingBean 失效那天,我们重读了 spring.factories 的加载顺序
引子我们做内部数据访问 starter 的时候封装了一个默认DataSource用ConditionalOnMissingBean(DataSource.class)留了个用户自定义就覆盖我的后门。本以为万事大吉。结果上线两周后测试库密码轮换监控里突然冒出一堆连不上测试库的报错——可我们业务代码明明白白用的是自己的DataSource啊。最后用ctx.getBeansOfType(DataSource.class)一查容器里竟然有 2 个 DataSource bean。那个本该缺席的默认 DataSource 悄悄注册了还默默建了一个 HikariCP 连接池连着测试库。这次事故逼我们把 Spring Boot 自动装配的加载顺序啃了一遍。结论是ConditionalOnMissingBean不是看全局有没有这个 bean它只看到当前这一步为止已经注册了哪些 bean——顺序错了它就会失手。这篇文章把自动装配机制和这个顺序坑讲透。问题自动装配到底装了什么你写的SpringBootApplication是个复合注解真正负责自动装配的是它身上的EnableAutoConfiguration。展开看自动装配就干了一件事在应用启动时按条件把一大批预先写好的 Configuration注册进容器。这些预先写好的配置类从哪来Spring Boot 2.6 及更早版本靠SpringFactoriesLoader读取所有 jar 包里META-INF/spring.factories文件的EnableAutoConfiguration键# spring.factoriesSpring Boot 2.6 及之前 org.springframework.boot.autoconfigure.EnableAutoConfiguration\ com.example.autoconfig.RedisAutoConfiguration,\ com.example.autoconfig.DataSourceAutoConfiguration而每个XxxAutoConfiguration类头上挂满了Conditional系列注解决定在当前环境下这个类到底装不装、里面的 bean 到底建不建。所谓自动本质是按条件批量注册配置 用户可覆盖。版本提醒Spring Boot 2.7 起spring.factories被标记弃用3.0 直接移除改用在META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports里列全类名。如果你在 3.x 上还按老写法放spring.factories自动装配类根本不会被加载——这是另一个高频坑。原理一自定义一个 starter 的自动装配一个最小可工作的自动装配类长这样以 Redis 为例Configuration ConditionalOnClass(RedisTemplate.class) // ① 类路径有 RedisTemplate 才装配 ConditionalOnProperty(prefix app.redis, name enabled, havingValue true, matchIfMissing true) // ② 开关默认开 public class RedisAutoConfiguration { Bean ConditionalOnMissingBean(RedisTemplate.class) // ③ 用户没定义才用这个默认 public RedisTemplateString, Object redisTemplate(RedisConnectionFactory factory) { RedisTemplateString, Object t new RedisTemplate(); t.setConnectionFactory(factory); t.setKeySerializer(new StringRedisSerializer()); t.setValueSerializer(new GenericJackson2JsonRedisSerializer()); return t; } }逐行解释第 2 行ConditionalOnClass(RedisTemplate.class)只有项目真的引入了spring-data-redisRedisTemplate在类路径上才装配这个类。你的 starter 被一个没用 Redis 的项目依赖时它自动隐身不会因缺类而启动报错。这是自动装配不污染别人的关键。第 3 行ConditionalOnProperty用配置项app.redis.enabled当总开关matchIfMissing true表示不配也默认开启。第 8 行ConditionalOnMissingBean(RedisTemplate.class)这才是用户可覆盖的后门——容器里到此刻还没有RedisTemplate类型的 bean才注册默认的有了就跳过。原理二Conditional 系列是自动装配的灵魂Spring Boot 提供了一整套条件注解自动装配类就是靠它们拼出按需装配的Configuration ConditionalOnWebApplication(type Type.SERVLET) // 仅 Servlet Web 环境才装 ConditionalOnClass(DispatcherServlet.class) // 类路径有这个类才装 ConditionalOnProperty(feature.x.enabled) // 配置开关为 true AutoConfigureAfter(DataSourceAutoConfiguration.class) // 排在数据源自动装配之后 public class XAutoConfiguration { Bean ConditionalOnMissingBean public XService xService() { return new XService(); } }逐行解释第 2 行ConditionalOnWebApplication你的 starter 被一个纯后端批处理程序依赖时它不是 Web 环境整个配置类跳过避免引入 servlet 相关 bean 导致冲突。第 4 行ConditionalOnProperty不带havingValue时配置存在且非false即生效常用来做功能开关。第 5 行AutoConfigureAfter是顺序编排很多自动装配之间有依赖比如用到DataSource的配置必须排在DataSourceAutoConfiguration之后否则它依赖的DataSourcebean 还没建好。这里的After/Before/Order只影响自动装配类之间的相对顺序不影响普通的ComponentScanbean。第 9 行ConditionalOnMissingBean不带参数时默认按方法返回类型XService判断。原理三ConditionalOnMissingBean 的检测窗口陷阱这是栽我们的根因必须讲清。ConditionalOnMissingBean检查的是到当前 bean 定义处理时刻为止容器中已存在的 bean而不是最终的全部 bean。而 Spring 处理 bean 定义是有先后顺序的先处理ComponentScan扫到的Component/Configuration包括你主应用包下的业务配置。再处理自动装配类EnableAutoConfiguration引入的那批且自动装配类之间按AutoConfigureBefore/After/Order排序。所以如果用户的自定义 bean 是通过ComponentScan注册的最常见写在主应用包下它先于自动装配处理ConditionalOnMissingBean能看到它正确缺席——这是正常情况。出问题的是下面这种// 业务模块里把自定义 DataSource 写在一个 Configuration 里注意不是 Component Configuration public class BizDataSourceConfig { Bean public DataSource dataSource() { // 业务自己的 DataSource return new HikariDataSource(...); } } // starter 里 Configuration ConditionalOnMissingBean(DataSource.class) // 本以为能检测到业务的 dataSource public class StarterDataSourceAutoConfig { Bean public DataSource dataSource() { return new HikariDataSource(...); // 结果也注册了 } }逐行解释第 3 行业务dataSource写在BizDataSourceConfig这个普通Configuration里。如果该配置类因为某种排序原因在 starter 的自动装配类之后才被处理比如 starter 用了AutoConfigureBefore抢先或业务配置本身又被别的自动装配Import延迟那么处理 starter 的ConditionalOnMissingBean那一刻业务的dataSource还没注册ConditionalOnMissingBean判定没有→ 默认 bean 被注册。第 12 行 starter 的dataSource于是也注册进去。由于业务的Primary让注入走业务那个表面上能跑但容器里实际上有 2 个 DataSource bean其中一个默默连着测试库、建着多余的连接池——直到密码轮换才炸出来。换句话说ConditionalOnMissingBean的Missing是时序相关的没看到不等于真的没有。这是自动装配最容易踩的顺序雷。我们的修复与验证定位靠这一行// 启动后 / 单元测试里打印确认到底注册了几个 MapString, DataSource dsMap ctx.getBeansOfType(DataSource.class); System.out.println(DataSource 数量 dsMap.size()); // 预期 1实际 2 dsMap.forEach((name, ds) - System.out.println(name - ds));确认有 2 个后修复有两招招一推荐把业务的自定义DataSource放在主应用包下、用Component/Configuration走组件扫描保证它先于自动装配被注册这样ConditionalOnMissingBean能正常看到它并让默认 bean 缺席。招二在业务配置类上显式声明AutoConfigureBefore(StarterDataSourceAutoConfig.class)强制它在 starter 自动装配之前处理。但AutoConfigureBefore只对自动装配类生效业务配置得先变成自动装配类进spring.factories/ imports 文件才行代价较大。我们选了招一把业务DataSource挪进主应用包下的Configuration问题立刻消失getBeansOfType回到 1 个那个连测试库的冗余连接池也随之消失。我的取舍判断自动装配是便利不是魔法更不该是黑盒用别人 starter 时遇到多了一个 bean配置没生效第一反应应该是getBeansOfType(XXX.class)看容器里到底有几个而不是盲目加Primary掩盖。Primary 能解决注入冲突但解决不了多余 bean 偷偷建连接池这种资源泄漏。写自己的 starter条件要写全套ConditionalOnClassConditionalOnPropertyConditionalOnMissingBean三件套尽量齐全既不让 starter 污染不需要它的项目也留好用户覆盖的口子。我们那次就是只写了ConditionalOnMissingBean没考虑顺序才埋雷。ConditionalOnMissingBean 别依赖全局唯一的假设它看的是时序窗口内的 bean。如果你的覆盖 bean 定义在一个可能被延后处理的Configuration里它就不可靠。稳妥的做法是让覆盖 bean 走组件扫描主应用包注册。Spring Boot 3.x 务必改用AutoConfiguration.imports文件别再写spring.factories否则自动装配类整批不加载排查起来非常迷惑。总结Spring Boot 自动装配 EnableAutoConfiguration触发 SpringFactoriesLoader或 3.x 的 imports 文件批量加载XxxAutoConfiguration 一堆Conditional决定装不装。它的价值是按需、可覆盖但ConditionalOnMissingBean的Missing是时序相关的——只看处理到当前时刻已注册的 bean。我们的事故正是业务DataSource因排序延后注册导致ConditionalOnMissingBean失手、默认 bean 偷偷注册、冗余连接池连着测试库。排查这类问题永远从getBeansOfType数 bean 开始。思考题你项目里引入的第三方 starter有没有可能偷偷注册了你不想要的 bean挑一个核心类型比如DataSource、RedisTemplate、RestTemplate跑一次ctx.getBeansOfType(XXX.class)看看数量是不是 1。如果不是 1试着用AutoConfigureBefore或挪动自定义 bean 的注册时机把它压回 1 个再观察启动日志和连接数。

相关新闻

怎样在Windows上轻松搞定PDF处理?Poppler-Windows的完整实战指南

怎样在Windows上轻松搞定PDF处理?Poppler-Windows的完整实战指南

怎样在Windows上轻松搞定PDF处理?Poppler-Windows的完整实战指南 【免费下载链接】poppler-windows Download Poppler binaries packaged for Windows with dependencies 项目地址: https://gitcode.com/gh_mirrors/po/poppler-windows 还在为Windows系统处理…

2026/10/10 18:58:27 阅读更多 →
百考通AI充分考量:开题一键生成,让学术研究起步更从容,覆盖全场景需求

百考通AI充分考量:开题一键生成,让学术研究起步更从容,覆盖全场景需求

开题报告是学术写作的第一步,也是决定论文方向与质量的关键环节。从选题定题到框架搭建,从梳理研究背景到规划研究方法,繁琐的流程常常让专科、本科及研究生们倍感压力。百考通AI(https://www.baikaotongai.com)凭借智…

2026/10/2 16:40:30 阅读更多 →
如何免费解锁Microsoft Office完整功能:Ohook终极激活指南

如何免费解锁Microsoft Office完整功能:Ohook终极激活指南

如何免费解锁Microsoft Office完整功能:Ohook终极激活指南 【免费下载链接】ohook An universal Office "activation" hook with main focus of enabling full functionality of subscription editions 项目地址: https://gitcode.com/gh_mirrors/oh/oh…

2026/10/14 0:16:10 阅读更多 →

最新新闻

Apereo CAS 服务注册表自动初始化(Service Registry Initialization)实战指南

Apereo CAS 服务注册表自动初始化(Service Registry Initialization)实战指南

后端认证鉴权单点登录 【免费下载链接】cas Apereo CAS - Identity & Single Sign On for all earthlings and beyond. 项目地址: https://gitcode.com/gh_mirrors/ca/cas 点击查看 免费下载 导读 Apereo CAS 在启动时会根据配置自动将 classpath 上的默认 JS…

2026/10/15 3:10:36 阅读更多 →
Start Bootstrap 模板库站点解析:Jekyll 驱动的模板目录、详情页与在线预览架构

Start Bootstrap 模板库站点解析:Jekyll 驱动的模板目录、详情页与在线预览架构

前端文档 【免费下载链接】startbootstrap A library of free and open source Bootstrap themes and templates 项目地址: https://gitcode.com/gh_mirrors/st/startbootstrap 点击查看 免费下载 本文以 Start Bootstrap 站点博客中的《Structural Updates》一文为…

2026/10/15 3:10:36 阅读更多 →
PathOfBuilding完整使用攻略

PathOfBuilding完整使用攻略

PathOfBuilding完整使用攻略 【免费下载链接】PathOfBuilding Offline build planner for Path of Exile. 项目地址: https://gitcode.com/GitHub_Trending/pa/PathOfBuilding PathOfBuilding 是流放之路(Path of Exile)的离线 Build 规划工具&am…

2026/10/15 3:10:36 阅读更多 →
英伟达开源SoL-Pi:AI自己研究出优化方案,为Agent Harness省下64% Token

英伟达开源SoL-Pi:AI自己研究出优化方案,为Agent Harness省下64% Token

摘要:2026年9月11日,英伟达NVLabs开源SoL-Pi——不是新框架,不是新模型,而是一层“效率增强层”。装在开源Agent Harness Pi之上,Token消耗降低45%-64%,API成本降低50%-54%。最引人注目的不是性能数据&…

2026/10/15 3:10:36 阅读更多 →
网络安全工程师成长路线图,从小白到大神分阶段规划

网络安全工程师成长路线图,从小白到大神分阶段规划

夯实基石:初级工程师的入门必修课对于刚踏入网络安全领域的新人而言,首要任务不是盲目追求高深的攻防技巧,而是构建稳固的地基。这一阶段的核心目标是成为一名合格的初级安全工程师,重点在于对网络原理的深刻理解与 Linux 系统的熟…

2026/10/15 3:10:36 阅读更多 →
杂交瘤HAT筛选后集落稀疏怎么办?从融合效率、HGPRT到铺板密度的7项排查

杂交瘤HAT筛选后集落稀疏怎么办?从融合效率、HGPRT到铺板密度的7项排查

摘要: 杂交瘤细胞融合后进入HAT选择培养,是单克隆抗体制备流程中非常关键的一步,但实验中经常出现集落稀疏、孔内细胞逐渐消失甚至整块板无细胞存活等问题。不同失败表现背后的原因并不相同:融合后24-48小时即出现大量细胞碎片&am…

2026/10/15 3:09:36 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 7:53:34 阅读更多 →