spring循环依赖
- what
- 实例化一个完整的bean主要分两步,实例化(调用构造器在堆内存中分配一块内存)和初始化(给属性赋值);
- ClassA中有ClassB属性,ClassB中有ClassA属性,导致在bean初始化填充属性时,导致循环依赖
- when
- 在bean生成周期的属性填充阶段(populateBean)
- why
- ClassA中有ClassB属性,ClassB中有ClassA属性,导致在bean初始化填充属性时,导致循环依赖
- how(如何解决)
- 使用三级缓存,DefaultSingletonBeanRegistry
-
缓存 存储的内容 作用 备注 一级缓存
成品对象 二级缓存 半成品对象,只做了实例化(在堆内存中分配了空间),未做初始化 三级缓存 lambda表达式 获取源对象或代理对象 AbstractAutowireCapableBeanFactory#doGetBean中
getEarlyBeanReference逻辑(生成代理对象或原对象)
QA:
q:可以只用一个map集合吗?
a:可以,但不优雅,需要区分一个实例的半成品和成品,通过在key上加前缀等方案做区分,代码不友好;
q: 只用两级缓存,可以吗?
a:如果没有动态代理,可以;
q:为什么有动态代理就需要第三级缓存?
a:动态代理的生成在bean生命周期的BeanPostProcessor的postProcessAfterInitialization方法中实现,而bean的属性填充在此之前,所以此时并没有创建出对应的代理对象(如果需要代理对象的话); 所以需要提前生成代理对象,但spring无法感知是否需要生成代理对象(是由业务代码决定的),所以需要的属性填充之前唯一确定是原始对象还是代理对象,而属性的赋值时间也不可控,所有通过lambda表达式类似回调的机制在属性填充时确定是原对象还是代理对象。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南