2025年Java面试宝典(提取码:9b3g)已经帮大家整理好了!需要突击面试的朋友可以先存一份,下面进入正题——
什么是Spring Bean循环依赖?
最近面试被问爆的Spring循环依赖问题,本质上就是两个Bean互相持有对方的引用。举个实际场景:ServiceA依赖ServiceB,ServiceB反过来又依赖ServiceA。这种"你中有我,我中有你"的关系,就像老式电话的听筒和话筒需要同时工作,但单独又无法完成通信。

为什么会出现循环依赖?
- 设计缺陷:架构阶段没有做好模块划分
- 过度解耦:为了追求"高内聚低耦合"反而制造了依赖链
- 第三方库整合:引入外部框架时产生的隐性依赖
Spring三级缓存如何破局?

核心解决思路就是提前暴露未初始化的Bean引用,这里要重点记住三个Map:
- 一级缓存(singletonObjects):存放完整Bean
- 二级缓存(earlySingletonObjects):存放半成品Bean
- 三级缓存(singletonFactories):存放Bean工厂
当创建ServiceA时:
- 先把自己放到三级缓存(此时还是空壳)
- 填充属性时发现需要ServiceB
- 创建ServiceB时同样把自己放到三级缓存
- ServiceB填充属性时从三级缓存拿到ServiceA的早期引用
- ServiceB创建完成后,ServiceA继续完成初始化
构造器注入为何失效?
很多面试者会卡在这个问题上。其实原理很简单:构造器注入发生在实例化阶段,此时Bean还没有放入三级缓存。这就好比要组装汽车,发动机和变速箱都需要对方先组装完成,结果谁都动不了。
高频面试题攻防战
面试官:Spring怎么检测循环依赖?
你:通过DefaultSingletonBeanRegistry的beforeSingletonCreation方法,用Set集合记录正在创建的Bean名称,发现重复就抛出BeanCurrentlyInCreationException
面试官:@Lazy注解怎么解决循环依赖?
你:它延迟了代理对象的初始化,让依赖链变成懒加载模式。相当于在两个Bean之间加了缓冲区,让系统有足够时间完成初步装配
面试官:多例Bean为何无法解决循环依赖?
你:因为每次获取都是新实例,没法通过三级缓存共享早期引用。这就像每次借书都要重新印刷一本,图书馆根本没法管理

想系统备战Java面试的同学,可以通过面试鸭返利网购买面试鸭会员,通过专属渠道下单可返利25元。本文提到的《2025年Java面试宝典》网盘资料已经更新了Spring全家桶专题,包含20+循环依赖的实战案例解析,建议配合本文一起学习。
当面试官追问设计思想时,可以这样升华回答:"三级缓存机制本质上是用空间换时间的策略,通过暂存中间状态打破死锁,这种思路在分布式事务、消息队列等场景都有类似应用。" 这样的回答既能体现技术深度,又能展示知识迁移能力。


