Spring的三级缓存解决循环依赖

Spring的三级缓存解决循环依赖
赵海波Spring的三级缓存以及循环依赖
什么是循环依赖:
假设我们有两个类 A 和 B,类A和类B的实例互为成员变量即为循环依赖。
什么情况下会出现死循环?
当 Spring 框架启动后,开始根据注解将类 A 实例化并注入到容器当中,在实例化 A 之后就会尝试获取类 B 的实例来进行依赖注入。

三级缓存是什么
①一级缓存:单例池,缓存已经经历了完整的生命周期,已经初始化完成的bean对象
②二级缓存:缓存早期的bean对象(生命周期还没走完)
③三级缓存:缓存的是ObjectFactory,表示对象工厂,用来创建某个对象的
| 缓存名称 | 源码名称 | 说明 |
|---|---|---|
| 一级缓存 | singletonObjects | 单例池,缓存已经初始化完成的bean对象。 |
| 二级缓存 | earlySingletonObjects | 缓存早期的bean对象。(例如:只进行了实例化,还没有进行依赖注入) |
| 三级缓存 | singletonFactories | 缓存的是ObjectFactory,表示对象工厂,用来创建某个对象的。 |
第一,先实例A对象,同时会创建ObjectFactory对象存入三级缓存singletonFactories
第二,A在初始化的时候需要B对象,这个走B的创建的逻辑
第三,B实例化完成,也会创建ObjectFactory对象存入三级缓存singletonFactories
第四,B需要注入A,通过三级缓存中获取ObjectFactory来生成一个A的对象,同时存入二级缓存,这个是有两种情况,一个是可能是A的普通对象,另外一个是A的代理对象,都可以让ObjectFactory来生产对应的对象,这也是三级缓存的关键
第五,B通过从通过二级缓存earlySingletonObjects 获得到A的对象后可以正常注入,B创建成功,存入一级缓存singletonObjects
第六,回到A对象初始化,因为B对象已经创建完成,则可以直接注入B,A创建成功存入一次缓存singletonObjects
第七,二级缓存中的临时对象A清除
三级缓存解决循环依赖的局限性
三级缓存只是解决了构造函数之后的循环依赖问题,那么构造函数的循环依赖问题怎么解决呢?
- Spring 给我们提供了一个 @Lazy 注解,也叫懒加载,或延迟加载。被这个注解修饰的对象,只有在使用的时候才会创建实例,那时单例池中的其他对象都已经创建好了,便解决了循环依赖的问题。
三级缓存机制只能解决单例Bean的循环依赖问题,对于原型(prototype)Bean的循环依赖无能为力








