什么是spring循环依赖
- 在创建bean的过程中,类a需要类b才能创建,类b也需要类a才能创建造成死循环
缓存怎么解决
- bean的创建有三步,实例化,填充属性,初始化
- 我们将实例化这种半成品放入一个缓存
- a实例化把a放入,b实例化要a在缓存中有,可解决循环依赖
spring三级缓存
- spring通过三级缓存来避免循环依赖
- 创建a对象时发现需要b,把a放入三级缓存
- 创建b时需要a,把a放入二级缓存并删除三级中的a
- b直接晋升一级缓存并删除三级中的b
- a晋升至一级缓存,创建完成
为什么不能用二级缓存呢
-
因为有aop的代理对象,在创建b需要a时,二级缓存只能获取到原本对象而不能获取到代理对象
-
创建代理对象有后置处理和提前处理两个入口,而后置处理是初始化之后才能执行的,所以我们的动态代理使用的提前处理
-
于是我们除了单例池,半成品池,我们又有了一个工厂池,对象实例化a之后放入工厂池,并且创建动态代理(因为后面b创建时get了a,需要提前引用)
-
然后创建b放入工厂池(因为a的刚刚已经搞了,创建b的时候没人引用b,所以不需要创建动态代理),a放入半成品池(二级缓存)
-
然后b填充属性初始化,通过后置处理创建代理对象,然后b放入一级缓存(单例池)
-
然后a进入一级缓存(已经创建代理,无需后置创建)
总结
- 三级缓存时为了解决aop代理问题,创建b对象时,需要获取a(提前引用a,创建a时因为没有b所以没有提前引用),此时a在三级缓存通过提前引用获取代理对象给b访问,从而完美解决这个问题,虽然b也放在的三级缓存中,但因为没有引用b,所以b是没有提前代理的,等a到了二级,b就填充属性,初始化到了一级,然后才获取代理对象