新闻详情

新闻详情

首页 / 资讯中心 / 详情

Spring 循环依赖:三级缓存背得再熟,不如看这 3 个线上坑

发布时间:2026/11/10 18:26:25来源:尧图网络
Spring 循环依赖:三级缓存背得再熟,不如看这 3 个线上坑
循环依赖是 Spring 项目里一不留神就会碰到的问题尤其在多人开发的项目里两个人各写各的 Service一个要调 A一个要调 B合代码时谁也没注意互相引了——启动直接红字BeanCurrentlyInCreationException: Error creating bean with name a: Requested bean is currently in creation: Is there an unresolvable circular reference?我最常碰到的还不是简单的 A 依赖 B、B 依赖 A 两两互指而是链式的A 注入 BB 注入 CC 又注入 A——三个类串成一个环启动必崩。下面从原理到解法讲透附能跑的代码。一、先 30 秒理解什么是循环依赖就是 A 依赖 BB 依赖 CC 又依赖 A对象创建时形成闭环ServicepublicclassA{privatefinalBb;// 依赖 B}ServicepublicclassB{privatefinalCc;// 依赖 C}ServicepublicclassC{privatefinalAa;// 又依赖回 A成环}注意这不是函数递归调用那种是死循环是对象创建时的相互依赖。环上有几个 bean 都叫循环依赖链式三个以上比两两互指更常见。二、补充知识Bean 的三种注入方式要理解循环依赖为什么难解先看 Spring 注入 Bean 的三种方式注入方式写法优点缺点构造器注入推荐构造器参数 /RequiredArgsConstructor依赖明确、final 不可变、对象创建即完整官方推荐循环依赖时启动即崩实例化阶段就卡住字段注入Autowired private B b;代码最少依赖藏在字段里难测试、难发现循环官方不推荐setter 注入Autowired setB(B b)可选依赖友好创建后依赖可变不如构造器稳推荐默认用构造器注入——依赖一目了然、不可变、好测试。只有遇到循环依赖时才用Lazy破环坑 1 讲别为了省事全程字段注入。三、3 分钟理论Spring 靠三级缓存解决Spring 创建单例 Bean 分三步实例化createBeanInstance调构造器new 出对象填充属性populateBean注入依赖初始化initializeBeanAOP 代理、init 方法等循环依赖卡在第 1、2 步之间。Spring 的处理是提前暴露对象构造完、还没填充属性时就先放进缓存让别人拿。它有三层缓存缓存作用singletonFactories三级存对象工厂提前暴露的关键earlySingletonObjects二级存提前暴露的早期对象singletonObjects一级存初始化完成的成品 Bean流程是这样的A 实例化完把自己塞进三级缓存 → 填充属性发现要 B → 去创建 B → B 实例化完发现要 A → 一级没有、二级没有、三级有B 从三级缓存拿到 A 的引用 → B 顺利初始化完进一级缓存 → A 拿到 B也完成初始化。关键结论三级缓存的加入前提是对象已经调过构造器了——所以setter/字段注入能解决循环依赖构造器注入解决不了后者直接抛BeanCurrentlyInCreationException。理论就这么多面试够用了。下面是真正折磨人的 3 个实战坑。坑 1构造器注入的链式循环启动直接崩就是最开始的报错。现在流行构造器注入最规范但多人开发时链式循环一来启动必崩ServicepublicclassA{privatefinalBb;publicA(Bb){this.bb;}}ServicepublicclassB{privatefinalCc;publicB(Cc){this.cc;}}ServicepublicclassC{privatefinalAa;// 依赖回 A成环publicC(Aa){this.aa;}}启动即报BeanCurrentlyInCreationException。解法 1Lazy推荐改动最小——打破环上的任意一条边ServicepublicclassC{privatefinalAa;publicC(LazyAa){this.aa;}// 延迟解析环被打破}Lazy让 Spring 先注入一个代理对象真正调用时才去拿目标 Bean。解法 2换成字段注入不推荐用它掩盖问题ServicepublicclassC{AutowiredprivateAa;// 字段注入走 setter 流程能过}字段注入本质是填充属性阶段注入走了三级缓存路径所以能解。但正如第二节说的字段注入是官方不推荐的方式——用它破环属于能跑但丑根治看坑 3。坑 2循环依赖 事务/切面方法静默失效这个坑最阴启动不报错业务悄悄出错。场景A 有Transactional方法B 依赖 A。因为循环依赖B 在早期阶段拿到的 A不是最终完成 AOP 代理的成品而是提前暴露的早期对象ServicepublicclassA{AutowiredprivateBb;TransactionalpublicvoiddoSth(){}}ServicepublicclassB{AutowiredprivateAa;// 拿到的可能是早期对象publicvoidcall(){a.doSth();// 事务可能没生效}}结果就是doSth()里要么事务边界不对要么依赖切面的逻辑如Async、自定义 AOP表现诡异排查起来极其费时——因为你单测、正常调用都对只有走这条循环链路时才坏。解法还是Lazy让 B 真正调用 A 时才解析保证拿到的是完整代理ServicepublicclassB{AutowiredLazyprivateAa;// 真正调用时才解析拿完整代理}教训看到循环依赖 事务/切面组合别能跑就行必须把代理问题一起验证否则上线就是事故。坑 3循环依赖往往是设计坏味道这是我最想强调的一点。两个或多个Service 互相注入八成是职责边界划错了。最常见的案例A 其实只需要 B 的某个动作却直接注入了 B 的整个能力。正确的重构方向按优先级抽公共依赖把互相调用的那部分逻辑下沉到独立的 Service两边都依赖它环就断了单向调用审视业务很多互相调用其实有一方是多余的事件解耦A 做完发 Spring Event / 用 MQB 监听处理彻底不互相持有// 重构后A 只依赖抽出来的 CommonService不再反向ServicepublicclassA{privatefinalCommonServicecommonService;// 单向}ServicepublicclassCommonService{// 谁都不回依赖 A环断了}Lazy是止痛药重构才是根治。如果项目里循环依赖超过 2 处先别急着Lazy想想是不是设计该调了。总结场景结论构造器注入循环依赖启动即崩用Lazy或改字段注入setter/字段注入循环依赖三级缓存能解但慎用循环依赖 事务/切面可能静默失效必须验证代理多处循环依赖重构边界抽公共 Service 或事件解耦你项目里遇到过最诡异的循环依赖是啥是启动崩还是业务悄悄错评论区聊聊。相关阅读Spring 事务失效的 11 个真实场景——和这篇的坑 2 正好能串起来都是代码看着对、运行出问题的典型。本文首发于公众号「今天写BUG了么」关注看更多
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

【外设】之大彩串口显示屏 2026/11/10 4:49:37

【外设】之大彩串口显示屏

大彩串口屏初步使用 1 .官网下载 STM32 屏幕 GUI 设计资料 http://www.gz-dc.com/category/typeid/4112 找到 STM32 Keil 工程,移植相关代码因项目而异进行移植,由于项目简单,本人只对用到的指令接口进行修改。 比如:注意事项&…

阅读更多 →
无法下载Windows系统iso文件 2026/11/9 8:37:19

无法下载Windows系统iso文件

当我遇到这个问题的时候,我打开了一个网站: 登录 然后我打算下载的时候: 突然那个官方的连接就可以下载了:

阅读更多 →
【清华代码熊】DeepSeek V4.1 Flash 后训练详解 2026/11/10 9:14:31

【清华代码熊】DeepSeek V4.1 Flash 后训练详解

📌 上期解析了 DeepSeek V4.1 Flash 模型架构改进,本期解析 DeepSeek V4.1 Flash 预训练/后训练技术: 🌟 预训练:45T 文本 多模态混合语料、直接训练 sparse attention(取消 DeepSeek V4 的 dense 冷启动&…

阅读更多 →
Shuffle-R1: Efficient RL framework for Multimodal Large Language Models via Data-centric Dynamic ... 2026/11/10 1:10:29

Shuffle-R1: Efficient RL framework for Multimodal Large Language Models via Data-centric Dynamic ...

文章主要内容和创新点 主要内容 本文聚焦于多模态大语言模型(MLLM)强化学习(RL)训练中的效率问题,提出了一个名为Shuffle-R1的框架。研究发现,当前RL训练存在两个关键缺陷: 优势值坍缩(Advantage Collapsing):批次中大多数优势值集中在零附近,导致有效梯度信号被淹…

阅读更多 →
PRvL: Quantifying the Capabilities and Risks of Large Language Models for PII Redaction 2026/11/10 15:15:31

PRvL: Quantifying the Capabilities and Risks of Large Language Models for PII Redaction

一、文章主要内容总结 本文聚焦于利用大型语言模型(LLMs)实现个人身份信息(PII)脱敏的研究,旨在解决传统脱敏方法(如基于规则的系统、领域特定命名实体识别(NER)模型)泛化能力差、跨格式/跨语境适应性弱的问题。 研究通过全面评估多种LLM架构(包括密集型LLM(D-LLM…

阅读更多 →
LLaVA-RE: Binary Image-Text Relevancy Evaluation with Multimodal Large Language Model 2026/11/10 17:14:10

LLaVA-RE: Binary Image-Text Relevancy Evaluation with Multimodal Large Language Model

文章主要内容和创新点 主要内容 本文聚焦于二进制图像-文本相关性评估任务(判断图像与文本“相关”或“不相关”),针对该任务中文本格式多样、相关性定义随场景变化等挑战,提出了基于多模态大语言模型(MLLM)的解决方案LLaVA-RE。 模型设计:LLaVA-RE基于LLaVA 1.5架构,…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉