spring循环引用(bean的循环依赖)解决方案


使用三级缓存来解决循环依赖问题,                      注意:只能解决set方式的依赖注入,构造器方式的不行

一级缓存:singletonObjects,单例对象池,存放完整的SpringBean,也就是走完了整个bean创建生命周期过程。

二级缓存:earlySingletonObjects,早期单例对象。起到复用的作用,多个类都有循环引用该类,那么直接取出来就行。

三级缓存:singletonFactories,单例工厂对象。起到创建代理对象的作用,比如AOP等增强,将实例对象封装增强后返回

 

我们使用案例说明一下,假如A类依赖B对象, B依赖A对象

具体步骤如下:

1.A依赖B,B依赖A,容器将所有beanName循环出来依次加载bean

2.先实例化A,默认允许开启循环依赖,封装A对象单例工厂对象放入三级缓存中

3.设置A属性值(属性注入),发现依赖B对象,先从一级缓存缓存查找,没有的话去二级缓存查找,没有的话最后从三级缓存查找。 

4.最终未发现B类对一个的实例,还没有被加载,然后先去加载实例化B对象,并且封装B对象对应单例工厂对象,放入三级缓存。

5.设置B属性值(属性注入),发现依赖A对象,先从一级缓存缓存查找,没有的话去二级缓存查找,没有的话最后从三级缓存查找。

6.找到刚才放入三级缓存中的A对象封装的单例工厂对象,然后调用扩展方法,再创建A类的代理对象放入二级缓存中返回。

7.此时B对象属性装配完毕,B对象正常创建放入一级缓存,删除三级缓存对应单例工厂对象。

8.此时返回刚才创建的B对象给A对象里面对应赋值。

9.此时A属性装配完毕,将生成的A对象的代理对象赋值给A对象后,放入一级缓存中,删除二级缓存中对应对象。

 

那使用两级缓存不行吗,为什么一定要用到三级缓存呢?

其实代码实现上完全可以的,但是考虑到设计模式上一级缓存中都是跑完全流程后完整的对象,

如果直接将三级缓存中生产的不完整对象放入一级缓存,违背了单一职责原则,而且也不好维护,更失去了扩展的功能。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM