本文主要是介绍Spring如何解决循环依赖的,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
目录
Spring使用三级缓存解决循环依赖
一级缓存能解决循环依赖问题吗?
二级缓存SingletonObject和SingletonFactory可以解决循环依赖吗?
二级缓存SingletonObject和EarlySingletonObject可以解决循环依赖吗?
Spring使用三级缓存解决循环依赖
三级缓存:
- SingletonObject:全成品(10):key:beanName value:实例化并初始化完成的对象
- EarlySingletonObject:半成品(5):key:beanName value:实例化好的对象(如果需要aop代理,则此时已被Aop代理)
- SingletonFactory:半半成品(3):key:beanName value:ObjectFactory
一个对象进入缓存的顺序:
- 初始都是进入到三级缓存,一旦有人引用它将他提为二级缓存,创建完毕之后进入一级缓存,
- 每个对象只存在于一个缓存中, 没人引用它最后它初始化完毕后也会从三级缓存直接进入一级缓存
解决循环依赖的过程总结:
- A实例化后放入三级缓存,发现依赖B又去初始化B
- B实例化后放入三级缓存,发现依赖A又去初始化A,此时发现A在三级缓存中,将A提到二级缓存后依赖进去,然后初始化B最后将B放入一级缓存
- 然后A将B的依赖解决后,继续创建直到完毕
更加详细的源码过程如下:
spring循环依赖解决原理:循环依赖:A->B B->A
创建A:
- 依次从一级缓存,二级缓存,三级缓存获取看有没有,一旦获取到直接返回
- 发现没有所以创建:
- 首先实例化new,然后直接放入三级缓存:beanName:a,value:a对应的ObjectFactory(这是以防循环依赖的,此时是半半成品,所以放入最原始的缓存)
- populate执行autowired
- 初始化(beforeInit init afterInit)
- 放入ioc容器(放入一级缓存,并从二三级缓存移除)
创建B:
- A的populate执行autowired会去创建B
创建B的过程:
- 依次从一级缓存,二级缓存,三级缓存获取看有没有,一旦获取到直接返回
- 发现没有所以创建:
- 首先实例化new,然后直接放入三级缓存:beanName:b,value:b对应的ObjectFactory(这是以防循环依赖的,此时是半半成品,所以放入最原始的缓存)
- populate执行autowired
- 初始化(beforeInit init afterInit)
- 放入ioc容器(放入一级缓存,并从二三级缓存移除)
创建B:
- B的populate执行autowired会去创建A
- 创建A:
- 依次从一级缓存,二级缓存,三级缓存获取看有没有,此时发现最后面的三级缓存有A,
- 所以将A从三级缓存获取出来调用其getObject获得(此方法里也处理了aop), 并将其移动到二级缓存,成了5成品,别人如果再来获取可以直接使用这个5成品,没必要再使用3成品了,
- 接着B执行完populate后继续创建完毕(B创建完毕后此时B在一级缓存,A被B提到了二级缓存)
- 创建B完成后:然后程序返回到A的populate之后继续创建A(此时A也被一入了一级缓存,A和B都在一级缓存)
一级缓存能解决循环依赖问题吗?
不能
因为全成品和半成品放到一起的话,半成品有可能被提前获取走,这时候还没有被赋值,所以会有问题。
二级缓存SingletonObject和SingletonFactory可以解决循环依赖吗?
可以,但是有缺点
不是全成品就都放到SingletonFactory,其他bean使用这个半成品的时候都需要去SingletonFactory获取并执行其getObject方法。在这里可能会被很多bean调用很多次,比如A依赖B,C,D,E.....,而他们都依赖了A,B,C,D,E.....,初始化完成都在在A初始化完成之前,B,C,D,E...都会调用A的getObject
二级缓存SingletonObject和EarlySingletonObject可以解决循环依赖吗?
可以是可以 但是非常不好
这样的话,我们在向EarlySingletonObject里面放对象的时候就得首先判断是否需要提前Aop代理然后放进去。不需要还好,如果需要的话,生成代理放进去,但是最后没有人来引用,不是白生成了吗,如果白生成很多,那就很不好了因为后面AOP代理并没有用到这个提前的Aop代理,一般的代理是在initlize的AfterInit后置处理器中
这篇关于Spring如何解决循环依赖的的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!