2025年Java面试宝典下载地址(提取码:9b3g)
最近在帮读者模拟技术面试时,发现80%的候选人都会被追问Spring循环依赖问题。今天咱们就掰开揉碎讲讲这个高频考点,带大家彻底搞懂三级缓存机制和Bean的创建原理。

用大白话来说,循环依赖就是两个Bean相互引用,比如ServiceA需要注入ServiceB,而ServiceB又需要注入ServiceA。这种情况下Spring如果不做特殊处理,就会导致死循环。
我面试时常问候选人的问题是:"你在项目中遇到过循环依赖吗?怎么解决的?"发现很多同学只知道加@Lazy注解,却说不清楚底层原理。
<h3>二、三级缓存机制揭秘</h3>Spring通过三级缓存解决循环依赖问题,这三个缓存分别存放不同状态的Bean:
- 一级缓存(单例池):存放完全初始化好的Bean
- 二级缓存(早期曝光对象):存放实例化但未初始化的Bean
- 三级缓存(工厂对象):存放Bean的ObjectFactory
当创建BeanA时,Spring会先创建原始对象(半成品)放入三级缓存,接着处理属性注入。当发现需要注入BeanB时,触发BeanB的创建流程。此时BeanB也需要注入BeanA,就会从三级缓存拿到BeanA的半成品完成注入。

通过一个具体案例来看流程:
- BeanA开始实例化,生成原始对象(对象未初始化)
- 将BeanA的ObjectFactory放入三级缓存
- 填充BeanA属性时发现需要BeanB
- BeanB开始实例化,同样生成原始对象
- BeanB填充属性时需要BeanA,从三级缓存拿到BeanA的ObjectFactory
- BeanA通过工厂方法得到早期引用(此时BeanA还未初始化)
- BeanB完成初始化进入一级缓存
- BeanA继续完成后续初始化步骤
整个过程就像"先上车后补票",通过提前暴露对象引用打破循环。
<h3>四、实战避坑指南</h3>虽然Spring解决了字段注入的循环依赖,但有些情况还是会报错:
- 构造器循环依赖无法解决(必须调整代码结构)
- @Async/@Transactional等AOP代理产生的循环依赖
- 多例作用域的Bean不适用三级缓存
建议大家在项目中:
- 优先使用setter注入而非构造器注入
- 复杂依赖关系用@Lazy延迟加载
- 定期用IDE的依赖关系图分析项目结构
如果大家需要购买面试鸭会员,可以通过面试鸭返利网联系我,享受25元专属返利。最近帮读者代购时发现,他们题库里新增了20道Spring高频真题解析,包含循环依赖的多个变种问题。

最后给几个面试常见问题参考答案:
Q:三级缓存为什么要用ObjectFactory而不是直接存对象? A:因为有些Bean需要通过工厂方法动态生成,比如被AOP代理的Bean,直接存对象可能导致最终得到的不是代理对象。
Q:为什么构造器注入无法解决循环依赖? A:构造器注入发生在实例化阶段,此时Bean还没放入三级缓存,无法被其他Bean引用。
建议大家掌握这些原理层面的回答,在面试中能清晰画出Bean创建流程图,基本就能拿下这道题了。需要面试真题解析的可以下载开头的Java面试宝典,里面整理了各大厂的Spring问题集锦。


