发现Spring三级缓存没有写到博客里,这里从自己的笔记迁移一下,补上:
创建的都是单例,如果是构造方法注入,不能解决;如果是设值方法注入,用三级缓存解决:
DefaultSingletonBeanRegistry:singletonObjects
earlySingletonObjects
singletonFactories
代码流程:
bean在createBeanInstance后,populateBean前:
DefaultSingletonBeanRegistry:addSingletonFactory:
将ObjectFactory放到三级缓存。ObjectFacotry的getObject能得到自己这个bean。AbstractBeanFacotry:doGetBean:
DefaultSingletonBeanRegistry:getSingleton(String beanName):
自己里的bean获取自己时,一级缓存里没有,而且正在创建中,二级缓存里也没有,就调用三级缓存的ObjectFacotry的getObject,获取bean,放到二级缓存,移出三级缓存。AbstractBeanFactory:createBean之后,DefaultSingletonBeanRegistry:addSingleton:
bean放到一级缓存,移出二级缓存,移出三级缓存。
示例:
A中有B,B中有A。
A在实例化后,填充B前,把ObjectFactory放到三级缓存里。 (对应:addSingletonFactory)
B在实例化后,填充A时,一级缓存没有,而且A在创建中,找二级缓存,二级缓存没有,从三级缓存调用ObjectFactory的getObject得到A。将A放到二级缓存,移出三级缓存。 (对应:getSingleton)
B填充属性和初始化后,将自己放到一级缓存,移出二级缓存,移出三级缓存。
A填充B时,能从一级缓存获得B。
A在填充属性和初始化后,将自己放到一级缓存,移出二级缓存,移出三级缓存。 (对应:addSingleton)
核心在于:
B能拿到没有填充属性的A。
总结:
三级缓存适用于单例间循环依赖。
适用于设值方法或者注解注入,也就是非构造方法注入。三级缓存存的是ObjectFactory,为的是用户能干预bean的生成。
三级缓存里的ObjectFactory的getOject,走的是getEarlyBeanReference得到的,里面会判断一下所有的BeanPostProcessor中是不是有实现了SmartInstantiationAwareBeanPostProcessor接口,是bean就会是这个接口的getEarlyBeanReference返回值。AbstractAutoProxyCreator也实现了这个接口。
实例化了就会到三级缓存,被执行了ObjectFactory的getObject,就会到二级缓存,填充属性、初始化了,就会到一级缓存。