循环依赖bean的创建过程
假设需要创建两个bean,a和b,并出现循环依赖。这里a和b都应是单例的,注入方式为setter注入
@Component
public class A {
@Autowired
private B b;
}
@Component
public class B {
@Autowired
private A a;
}
假设Spring容器需要先创建a,则将会执行下列流程
- 依次检查一级缓存
singletonObjects、二级缓存earlySingletonObjects、三级缓存singletonFactories。由于是第一次获取a,无法从缓存直接返回 - 实例化
a对象 - 将可以获取
a对象的单例工厂放进三级缓存singletonFactories中 - 设置
a对象的属性,此时发现需要依赖b,则转向获取b - 依次检查缓存,由于是第一次获取
b,无法从缓存直接返回 - 实例化
b对象 - 将可以获取
b对象的单例工厂放进三级缓存singletonFactories中 - 设置
b对象的属性,此时发现需要依赖a,则转向获取a - 依次检查缓存,在三级缓存中发现并获取
a。在三级缓存获取a的时候,假如有对bean进行AOP处理,会在此时处理并返回一个代理对象,否则返回a本身。在返回之前,会把这个返回的对象加入到二级缓存earlySingletonObjects中,同时把相应的三级缓存删除。 - 将
a设置到b对象的属性中 - 继续
b对象后续的创建过程,完整创建完b对象后,b对象将进入一级缓存singletonObjects,并删除相应的三级缓存。且返回给a对象设置属性使用 - 将
b设置到a对象的属性中 - 继续
a对象后续的创建过程,a存在于二级缓存,二级缓存中可能是已经进行AOP处理的代理对象,需要将这个代理对象放进一级缓存中,然后清除二级缓存
处理循环依赖的一些细节
- 非单例的bean无法解决循环依赖
- 构造器注入方式可能导致无法解决循环依赖,先创建的bean不能以构造器方式注入后创建的bean。先创建的bean还没放进三级缓存,就需要获取依赖的bean,导致创建过程死循环
- 常规的AOP处理在
BeanPostProcessor的postProcessAfterInitialization阶段。一般为AbstractAutoProxyCreator的postProcessAfterInitialization方法。只有在循环依赖出现的时候,才需要把AOP处理提前到从三级缓存取出的时候 - 二级缓存和三级缓存的设计是为了解决循环依赖的问题
- 三级缓存并不能提高性能,主要还是为了保持Spring原有的设计,在没有循环依赖的情况下,将AOP处理保留在
BeanPostProcessor的postProcessAfterInitialization阶段
PREVIOUSVue单文件组件基础结构
NEXTaxios发送请求参数