spring为什么不能只用一二级缓存来解决循环依赖?

Spring bean注入流程
类实例化 -> 属性注入 -> 执行初始化方法 -> (如果有需要)生成代理对象 -> 使用

二级缓存存在的问题
举例说明:A、B两个类相互依赖,初始化A的时候,

第一步实例化A完成(原始实例放入二级缓存),注入依赖属性B,一级缓存查询B没有,二级缓存查询B没有,

初始化B(放入缓存),注入依赖属性A,一级缓存查询A没有,二级缓存查询A注入(此时A是原始实例,未被代理),生成代理对象B,移入一级缓存,继续A属性注入(B的代理对象),A初始化完成。

B中的依赖对象A是未代理的,存在问题(环境中存在代理和未代理的两种类型的同一个对象A)。

如果上述流程放入二级缓存的是代理对象,则和spring bean生成流程(实例最后生成代理对象)相悖。

三级缓存解决的问题
A、B两个类相互依赖,初始化A的时候,第一步实例化A完成(生成对象工厂实例放入三级缓存),注入依赖属性B,一级缓存查询B没有,二级缓存查询B没有,

初始化B(生成对象工厂实例放入三级缓存),注入依赖属性A,一级缓存查询A没有,二级缓存查询A没有,三级缓存查询到A的对象工厂,生成A的代理对象,放入到二级缓存,注入A的代理对象完成,生成代理对象B,移入一级缓存。

继续A属性注入(B的代理对象),A初始化,生成A的代理对象,发现A的代理对象已存在,则跳过,放入一级缓存。此时A的代理对象也是提前生成的,但是仅针对循环依赖提前生成。

三级缓存正常生成流程

第一步实例化A完成(生成对象工厂实例放入三级缓存,此时虽然放入三级缓存,但没有生成代理对象),注入属性,执行初始化方法,生成代理对象,移入一级缓存。
其中创建AOP代理对象的子类是AbstractAutoProxyCreator,它实现了postProcessAfterInitialization方法,先判断初始化完成后的bean是否已经被动态代理,若已处理过,则直接返回,如果不需要动态代理,也直接返回;若需要处理,则生成动态代理,保存到一级缓存中。

Spring AOP代理对象创建流程

posted @ 2022-08-20 21:24  sahara-随笔  阅读(1336)  评论(0编辑  收藏  举报