Spring bean 的生命周期
- instantiation 通过反射调用构造函数
- populate properties
- before init
- aware
- init
- after init
- in use
- before destruction
为什么需要三级缓存
三级缓存是哪些
- 一级缓存: singletonObjects
- 二级缓存: earlySingletonObjects
- 三级缓存: singletonFactories
两级缓存可以解决循环依赖
对于不存在代理的对象,通过两级缓存即可解决循环依赖问题。假设需要创建A和B两个bean,A依赖B,B依赖A。创建流程:
- instantiation 实例化A
- 将A加入缓存中
- populate properties 填充A的属性,发现所需依赖的B未实例化
- instantiation 实例化B
- 将B加入缓存
- populate properties 填充B的属性,此时从缓存中拿到A填充到B当中
- init 完成B初始化
- 将B填充到A的属性中
- init 完成A初始化
三级缓存解决代理对象循环依赖
原因:避免破坏bean的生命周期
Bean被代理时,生成代理对象在postprocess这个步骤,是在属性填充之后执行的。
在上面的两级缓存的逻辑中,A的代理对象是在A属性填充后生成的,因此B依赖的是A的原始对象。为了解决这个问题,引入三级缓存。
三级缓存:A在实例化后,会将ObjectFactory放入三级缓存中,当B依赖A时,会从三级缓存中拿到ObectFactory并调用getObject方法,在getObject方法的逻辑中会判断A是否被代理,从而返回对应的代理对象或者原始对象,并将这个对象添加到二级缓存,然后从三级缓存中删除。这样做延迟了代理对象的创建,如果不存在循环依赖或者不存在AOP时,代理对象的创建不会提前,bean的生命周期不会被改变。