目录
二级缓存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方法。但是这个getObject其实只能执行一次,如果有多个bean的生成调用其getObject那么每个人拿到的代理都是不同的,就不是单例了。
二级缓存SingletonObject和EarlySingletonObject可以解决循环依赖吗?
可以 但是不好
这样的话,我们在向EarlySingletonObject里面放对象的时候就得首先判断是否需要提前Aop代理然后放进去。不需要还好,如果需要的话,生成代理放进去,但是最后没有人来引用,不是白生成了吗,如果白生成很多,那就很不好了因为后面AOP代理并没有用到这个提前的Aop代理,一般的代理是在initlize的AfterInit后置处理器中
猜测:
spring应该是先用到一级缓存和三级缓存 然后发现三级缓存的getObject只能调用一次
此时调用一次后因为是半成品又不能放入一级缓存 所以才想到二级缓存