Spring框架如何解决循环依赖
目录
- 一,什么是循环依赖
- 二、什么是三级缓存
- 三、Spring框架如何解决循环依赖
一,什么是循环依赖
例:类与类之间的依赖关系形成了闭环,例如A依赖了B,B依赖了C,C又依赖了A。
二、什么是三级缓存
在 Spring 框架中,三级缓存是解决循环依赖问题的核心机制,这三级缓存本质上是三个不同作用的 Map 集合,用于存储 bean 的不同状态
- 一级缓存(singletonObjects):存储完全初始化完成的单例 Bean(即经过实例化、属性注入、初始化方法执行后的最终成品)
时机:当 bean 完全初始化后,会从二级缓存或三级缓存移至此缓存 - 二级缓存(earlySingletonObjects):存储半成品 Bean(已实例化,但未完成属性注入、初始化)
注意:此缓存中的 bean 是 “半成品”,仅能被其他 bean 引用,自身还需继续完成初始化流程。 - 三级缓存(singletonFactories):存储 Bean 的工厂(ObjectFactory),用于 “按需创建” 半成品 Bean。当其他 Bean 首次需要引用当前 Bean 时,通过工厂生成 Bean 的早期引用(可能是原始对象或 AOP 代理对象)。
三、Spring框架如何解决循环依赖
A类依赖B类,B类依赖A类咋样解决?
我的思路:
首先创建A的时候创建一个A类工厂存入三级缓存中,然后注入B时,B还没创建,所以去创建B,先创建一个B类工存到三级缓存中,然后B又依赖A,从三级缓存中拿到A的工厂创建A的半成品,放到二级缓存中,并从三级缓存移除,B此时就可以注入A,B完成创建并放到一级缓存中,A此时也可以注入了B,A完成了创建也放到一级缓存中,并从二级缓存移除A。
注意:三级缓存中存放的工厂可以处理 AOP 代理场景,确保 B 依赖的 A 和最终生成的 A 是同一个对象(可能是代理对象),代理对象可以在AOP增强方法时使用。
A类依赖B类,B类依赖C类,C类又依赖了A咋样解决?
我的思路:
1.创建 A:
Spring 创建 A 时,将 A 的工厂对象存入三级缓存,此时 A 是 “半成品”(未完成属性注入)。
A 需要依赖 B,Spring 转而开始创建 B。
2.创建 B:
实例化 B 后,将 B 的工厂存入三级缓存。
B 需要依赖 C,Spring 转而开始创建 C。
3.创建 C:
实例化 C 后,将 C 的工厂存入三级缓存。
C 需要依赖 A,此时 Spring 尝试获取 A:
从三级缓存中获取 A 的工厂,通过工厂生成 A 的早期引用(可能是原始对象或代理对象),并将 A 移至二级缓存,同时删除三级缓存中的 A 工厂。
C 成功注入 A,完成属性注入和初始化,最终 C 被存入一级缓存。
4.继续创建 B:
B 依赖的 C 已存在于一级缓存,B 注入 C 后完成初始化,存入一级缓存。
5.继续创建 A:
A 依赖的 B 已存在于一级缓存,A 注入 B 后完成初始化,A从早期的二级缓存移除,并放到一级缓存中。
注意:无论循环依赖的链条多长,只要是单例 Bean 且使用 setter 注入,Spring 都能通过这种三级缓存的协作机制来解决,核心是通过提前暴露对象引用并合理管理不同状态的 Bean 缓存。