什么是循环依赖?Spring 如何解决单例 Bean 的循环依赖?

lnrk.cn 开封八大员报考服务
一、什么是循环依赖循环依赖两个或多个单例 Bean 互相持有对方作为依赖创建时形成死锁无法完成实例化。两种典型场景1. 双向依赖最常见A 里面依赖 BB 里面依赖 Ajava运行Component public class A { Autowired private B b; } Component public class B { Autowired private A a; }2. 多向循环A→BB→CC→A补充三种注入方式对循环依赖的支持setter / 字段注入Autowired 成员变量Spring 可以解决单例循环依赖构造器注入无法解决直接抛BeanCurrentlyInCreationExceptionprototype 多例 Bean完全不支持循环依赖每次新建对象缓存无效二、Spring 解决单例循环依赖核心原理三级缓存Spring 通过DefaultSingletonBeanRegistry维护三个 Map 缓存提前暴露半成品对象解决循环。三级缓存定义java运行// 一级缓存存放完全初始化好的成品单例 Bean private final MapString, Object singletonObjects new ConcurrentHashMap(); // 二级缓存存放实例化完成但还未填充属性、未初始化的半成品 Bean private final MapString, Object earlySingletonObjects new HashMap(); // 三级缓存存放 Bean 的工厂 ObjectFactory用于生成半成品 Bean支持AOP代理 private final MapString, ObjectFactory? singletonFactories new HashMap();各级缓存作用一级缓存 singletonObjects完整创建、属性填充、初始化完毕的 Bean对外正常使用。三级缓存 singletonFactories关键Bean 刚实例化new 对象后立刻把生成当前 Bean 的工厂存入三级缓存。 作用如果该 Bean 需要 AOP 动态代理ObjectFactory 会返回代理对象无 AOP 则返回原生半成品。二级缓存 earlySingletonObjects当出现循环依赖其他 Bean 需要引用半成品时 从三级缓存取出 ObjectFactory生成半成品 / 代理对象放入二级缓存并删除三级缓存对应记录。 避免每次都执行代理逻辑提升性能。缓存查找顺序获取单例 Bean 时顺序一级缓存 → 二级缓存 → 三级缓存一级有直接返回成品一级无、二级有返回半成品一二都无、三级有工厂创建半成品存入二级返回三、分步演示 A、B 循环依赖完整流程字段注入前提A、B 都是单例使用 Autowired 字段注入创建 A先判断一级缓存无 A标记 A 为「正在创建」反射 new A 对象实例化完成属性为空半成品将 A 的 ObjectFactory 放入三级缓存 singletonFactories开始填充 A 的属性发现依赖 B去获取 B创建 B一级缓存无 B标记 B 正在创建new B 半成品将 B 的工厂存入三级缓存填充 B 的属性发现依赖 A去获取 AB 获取依赖 A核心解决点一级缓存无 A二级缓存无 A三级缓存存在 A 的 ObjectFactory取出工厂生成 A 半成品将 A 半成品放入二级缓存 earlySingletonObjects删除三级缓存的 A将半成品 A 注入给 B 的属性B 填充完成执行初始化afterPropertiesSet、init-method完全初始化后的成品 B 放入一级缓存 singletonObjects删除二、三级缓存中 B 的记录回到 A 的属性填充现在可以拿到完整的成品 B注入 A 的属性A 完成初始化成品 A 放入一级缓存删除二三级缓存 A整个流程走完A、B 全部创建完成循环依赖解除。四、关键补充高频面试考点1. 为什么构造器注入无法解决循环依赖三级缓存存入工厂的时机是实例化new 对象之后。 构造器注入需要在 new 对象阶段就传入依赖此时对象还没创建无法提前存入三级缓存暴露半成品直接抛出异常。2. 为什么需要三级缓存只用二级行不行不行三级缓存是为了AOP 动态代理如果 Bean 需要代理ObjectFactory 内部会执行getEarlyBeanReference()创建代理对象若只有二级缓存提前暴露的只能是原生对象后续无法替换成代理对象会导致注入原生对象事务、切面失效。3. prototype 多例 Bean 为什么不能解决循环依赖多例 Bean 不会存入任何一级缓存每次获取都新建对象没有半成品缓存复用机制循环依赖直接无限创建对象报错。4. 开发如何避免循环依赖业务分层解耦调整依赖关系不要互相依赖使用构造器注入循环依赖会直接报错提前发现问题使用Lazy懒加载依赖注入代理对象延迟创建目标 Bean。五、总结循环依赖多个单例 Bean 互相依赖创建闭环Spring 仅支持单例 setter / 字段注入的循环依赖构造器、多例不支持核心方案三级缓存提前暴露半成品 Bean一级完整成品 Bean二级循环依赖临时半成品三级Bean 工厂支持 AOP 代理生成流程核心实例化后先放入三级缓存填充属性时若出现循环取出半成品注入对方完成创建。
lnrk.cn 咨询服务点

看完这篇还有疑问?

报考条件、材料清单、下一期窗口,直接走 在线咨询 或拨 18236992212。材料怎么填见 报名材料模板,常见陷阱见 避坑指南。

这篇文章讲了什么

你现在看的这篇,是 lnrk.cn 开封八大员报考服务整理的报考相关文章。不管是政策解读、材料指南还是案例复盘,写的时候都尽量用大白话,避免太多专业术语。

如果文章里提到的政策、材料要求和你现在的情况对不上,别自己对着文章硬套——政策一年一小变,你今年的情况可能和文章写的有出入。打个电话问一句最稳妥。

文章底部我们列了相关文章、最新文章、本周热门、今天热门、本月热门,你可以顺着往下翻。都是和你正在看的这篇主题相近的内容。

如果你觉得这篇文章有用,欢迎转给身边一起在工地干活的朋友。少走弯路,比什么都强。

还在自己琢磨报考条件?

文章写得再细,也代替不了对着你的具体情况判断一句。把学历、岗位、所在区县告诉我们,电话里几分钟给你个准话。

去在线咨询

材料不知道怎么填?

报名表、工作证明、学历验证、证件照,每一项都有容易踩的坑。提前看一遍清单,别等被退件才发现。

报名材料模板

公司要统一一批人考?

施工企业补齐项目班子持证人员,走批量通道更省事。材料统一收、统一审、统一考、统一领证。

企业批量通道

以上三个入口,你按自己情况选一个点就行。拿不准该点哪个的,直接打电话最快。

看完这篇文章别急着走——下面还有相关文章和热门文章推荐,都是和你正在看的这篇主题相近的。顺着往下翻,能把你这块的疑问一次性搞清楚。比你自己在搜索框里乱找效率高得多,也不用翻半天,省时间,记得收藏备用哈,谢谢。

FAQ

看文章时你可能还想问

我学历不高,能考八大员吗?

八大员报考对学历的要求不是很高,中专及以上相关专业毕业就有资格。专业不对口的,靠施工现场累计工作年限来凑——一般干个三五年就够了。具体你能报哪个岗,把学历和干了几年告诉我们,电话里几分钟给你个准话。

考试难不难,要考几门?

机考两科,一科基础知识、一科岗位实务。都是选择题为主,难度不算大,但需要你对题型熟悉。我们安排考前串讲和模拟上机,真正在现场干活的人基本都能一次过。

证书考下来有效期多久?

八大员证书需要继续教育延续。到期前我们会提醒你,别让证书超期失效。很多人考下来就不管了,等到投标要用才发现证书过期了,又得重新弄。

我在县里,跑市区不方便怎么办?

兰考、杞县、通许、尉氏、祥符这五个县的工友,材料可以拍照发我们预审,改完邮寄过来,不用专门跑一趟市区。只有考试那天需要本人到机考点。

这篇文章背后的服务

你现在看的这篇文章,是 lnrk.cn 开封八大员报考服务整理发布的。我们是开封本地做建筑岗位证书报考辅导的小团队,不搞那些把话说得特别满、绕开正规流程的歪门邪道,就老老实实帮你把政策讲清楚、把材料理顺、把考试安排好。

文章里的信息可能随政策调整而变化,以当期公告为准。拿不准的地方别自己对着旧文章猜,直接打 18236992212 问一句最稳妥。也可以填 在线咨询表单,工作时间内回电。

相关服务入口:政策动态 · 避坑指南 · 材料模板 · 企业通道 · 合作案例 · 关于我们。

如果你看完这篇文章还有别的疑问,不用翻来翻去找联系方式——页面最上面有电话 18236992212,随时打。工作时间基本都能接通。

觉得这篇文章有用,欢迎转给身边一起在工地干活的朋友。少走弯路,比什么都强。

关于 lnrk.cn 开封八大员报考服务

我们是开封本地做建筑岗位证书报考辅导的小团队。不搞那些把话说得特别满、绕开正规流程的歪门邪道,就老老实实帮你把政策讲清楚、把材料理顺、把考试安排好。

咨询电话 18236992212,邮箱 809451989@qq.com。工作时间内回电,周末休息但留言次工作日回。

我们在开封本地做了多年,不是外地远程客服。政策和流程都熟,接电话的就是干活的人。

有问题随时打,不用客气。

工作时间内基本都能接通。