Spring中如何解决循环依赖
八字真言:“三级缓存,提前暴露”
此文只是介绍简单的情况便于理解,实际上场景会更复杂、情况会更多,但是原理相通。
一、什么是循环依赖?
从字面上来理解就是A依赖B的同时B也依赖了A,就像下面这样

上图是简单的循环依赖,也会存在A依赖B,B依赖C,C依赖A这种循环,或者更复杂的情况。
(在实际工作中应该尽量避免出现循环依赖的情况)
二、什么情况下循环依赖可以被处理?

三、Spring是如何解决的循环依赖?
三级缓存:
一级缓存 : Map<string,object> singletonObjects,单例池,用于保存实例化、属性赋值(注入)、初始化完成的 bean 实例
二级缓存 : Map<string,object> earlySingletonObjects,早期曝光对象,用于保存实例化完成的 bean 实例
三级缓存 : Map<string,objectfactory<?>> singletonFactories,早期曝光对象工厂,用于保存 bean 创建工厂,以便于后面扩展有机会创建代理对象。
流程图:

总结:
假如testService1依赖testService2,testService2依赖testService1
Bean初始化流程:
- 创建 testService1实例,实例化的时候把 testService1 对象⼯⼚放⼊三级缓存,并提前先暴露出来;
- testService1 注⼊属性时,发现依赖 testService2,此时 testService2 还没有被创建出来,所以去实例化 testService2;
- 同样,testService2注⼊属性时发现依赖 testService1,它就会从缓存里找 testService1对象。依次从⼀级到三级缓存查询 testService1,从三级缓存通过对象⼯⼚拿到 testService1,发现 testService1虽然不太完善,但是存在,把 testService1 放⼊⼆级缓存,同时删除三级缓存中的 testService1,此时,testService2 已经实例化并且初始化完成,把testService2放入⼀级缓存
- 接着testService1继续属性赋值,顺利从⼀级缓存拿到实例化且初始化完成的testService2对象,testService1对象创建也完成,删除⼆级缓存中的 testService1,同时把testService1放⼊⼀级缓存
- 最后,⼀级缓存中保存着实例化、初始化都完成的 testService1、testService2 对象
本文作者:MuXinu
本文链接:https://www.cnblogs.com/MuXinu/p/18106258
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步