始于足下.|

MuXinu

园龄:2年7个月粉丝:3关注:1

Spring中如何解决循环依赖

八字真言:“三级缓存,提前暴露”

此文只是介绍简单的情况便于理解,实际上场景会更复杂、情况会更多,但是原理相通。

一、什么是循环依赖?

从字面上来理解就是A依赖B的同时B也依赖了A,就像下面这样
 
0
上图是简单的循环依赖,也会存在A依赖B,B依赖C,C依赖A这种循环,或者更复杂的情况。
(在实际工作中应该尽量避免出现循环依赖的情况)

二、什么情况下循环依赖可以被处理?

0

三、Spring是如何解决的循环依赖?

三级缓存:

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

流程图:

0

总结:

假如testService1依赖testService2,testService2依赖testService1
Bean初始化流程:
  1. 创建 testService1实例,实例化的时候把 testService1 对象⼯⼚放⼊三级缓存,并提前先暴露出来;
  2. testService1 注⼊属性时,发现依赖 testService2,此时 testService2 还没有被创建出来,所以去实例化 testService2;
  3. 同样,testService2注⼊属性时发现依赖 testService1,它就会从缓存里找 testService1对象。依次从⼀级到三级缓存查询 testService1,从三级缓存通过对象⼯⼚拿到 testService1,发现 testService1虽然不太完善,但是存在,把 testService1 放⼊⼆级缓存,同时删除三级缓存中的 testService1,此时,testService2 已经实例化并且初始化完成,把testService2放入⼀级缓存
  4. 接着testService1继续属性赋值,顺利从⼀级缓存拿到实例化且初始化完成的testService2对象,testService1对象创建也完成,删除⼆级缓存中的 testService1,同时把testService1放⼊⼀级缓存
  5. 最后,⼀级缓存中保存着实例化、初始化都完成的 testService1、testService2 对象

本文作者:MuXinu

本文链接:https://www.cnblogs.com/MuXinu/p/18106258

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   MuXinu  阅读(38)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起