循环依赖
循环依赖是指两个bean对象中的属性通过setter注入,在其实例化的时候当Bean1实例化时,为了给属性Bean2赋值就得要实例化Bean2。而Bean2在实例化时,同时也要为属性Bean1实例化Bean1,这样的话就会陷入一个无限循环了,而这就是Spring中的循环依赖问题。
解决方案:使用三级缓存的方式来解决
在解决 bean循环依赖的思路之前先来复习一下bean的生命周期,其包括的三个步骤:
- 实例化:执行bean的构造方法,bean中依赖的对象还未赋值
- 设置属性:给bean中依赖的对象赋值,若被依赖的对象尚未初始化,则先进行该对象的生命周期(递归)。
- 初始化:执行bean的初始化方法,回调方法等。
循环依赖的解决方法就是在实例化和设置属性之间引入缓存机制,把已经创建好实例但并没有设置属性的bean放到缓存中,缓存中存储的是没有设置属性的实例化对象。其三级缓存如下
级别 | 描述 | |
---|---|---|
singletonObjects | 一级缓存 | 用于存放完全初始化好的 bean,从该缓存中取出的 bean 可以直接使用 |
earlySingletonObjects | 二级缓存 | 存放原始的 bean 对象(尚未填充属性),用于解决循环依赖 |
singletonFactories | 三级缓存 | 存放 bean 工厂对象,用于解决循环依赖 |
循环依赖解决过程:
1、先从一级缓存 singletonObjects (一级缓存 )中获取取到则返回
2、如果一级缓存不存在则去二级缓存 earlySingletonObject (二级缓存)中获取得到,
3、如果二级缓存也不存在则去三级缓存 singletonFactories (对象工厂缓存)中创建,并添加到二级缓存中。