当前位置: 首页 > news >正文

Spring-循环依赖

预备知识

循环依赖开关(方法) - AbstractAutowireCapableBeanFactory#setAllowCircularReferences

  • 单例工程(属性) - DefaultSingletonBeanRegistry#singletonFactories
  • 获取早期未处理Bean (方法) - AbstractAutowireCapableBeanFactory#getEarlyBeanReference
  • 早期未处理Bean (属性) - DefaultSingletonBeanRegistry#earlySingletonObjects

循环依赖处理流程

案例代码:

@Component
public class ClassRoom {@Autowiredprivate Collection<Student> students;public Collection<Student> getStudents() {return students;}public void setStudents(Collection<Student> students) {this.students = students;}
}
@Component
public class Student {@Autowiredprivate ClassRoom classRoom;public ClassRoom getClassRoom() {return classRoom;}public void setClassRoom(ClassRoom classRoom) {this.classRoom = classRoom;}
}

这个例子ClassRoom里面注入了Student,Student里面又注入了ClassRoom。

首先要确保我们的循环依赖是单例的,然后再初始化单例Bean的时候会调用doGetBean方法,然后进入AbstractBeanFactory#doGetBean方法:
在这里插入图片描述
在getSington方法里面beforeSingletonCreation,有这样一个方法,这个方法会将当前正在创建的单例Bean放到singletonsCurrentlyInCreation中:
在这里插入图片描述
接着会调用我们拉姆达表达式穿进来的工厂createBean获取Bean,会判断是不是正在创建的Bean
在这里插入图片描述
如果是的话(前面在beforeSingletonCreation将当前创建的Bean放到了singletonsCurrentlyInCreation所以这里肯定是),会调用addSingletonFactory,会传进去一个拉姆达表达式:
在这里插入图片描述
这个时候singletonFactories就会存贮,并且earlySingletonObjects如果存在会移除这个Bean,同时将这个Bean放到已注册中:
在这里插入图片描述
接着就是这个Bean的populateBean逻辑,对依赖进行注入会处理依赖doResolveDependency:
在这里插入图片描述
由于我们注入Students是一个集合,所以会走multipleBeans这个处理:
在这里插入图片描述
这个时候又去getBean了,这个和我们上面ClassRoom走的是一样的流程,这个时候已经有两个了:
在这里插入图片描述
在Student注入的时候发现注入的字段又需要ClassRoom,于是又会去resolveDependency:
在这里插入图片描述
这个时候earlySingletonObjects里面没有,所以拿到了我们上面的singletonFactories中的singleFactory了,在拿到Bean以后就将singletonFactories中的移除了,同时将它放到earlySingletonObjects:
在这里插入图片描述
然后将这个ClassRoom的Bean注入到Student中:
在这里插入图片描述
我们可以看到这个时候ClassRoom里面是没有注入Students的:
在这里插入图片描述
接下来就是调用了addSington,里面如果判断是新创建的Sington做了这样几件事情:1)移除将当前Bean放到singtonObjects中 2)将singtonFactories中的singleFactory移除
在这里插入图片描述
然后回到了ClassRoom,这个时候Student的Bean已经进行了创建,进行注入即可。同时将这个Bean从创建中进行移除。
在这里插入图片描述
这就解决了循环依赖,我的理解是通过Map存储早期的Bean,然后注入的也是早期的Bean,等到它依赖的Bean完成注入的时候,注入的早期的Bean的引用也会发生变化,类似于一个延迟加载。


http://www.mrgr.cn/news/21590.html

相关文章:

  • SIGMOD-24概览Part2: Industry Session (Query Engines)
  • Springboot工程配置https访问
  • 英文翻译工具怎么选?这4款值得收藏。
  • gpedit.msc本地组策略编辑器,结果发现竟然打不开了
  • sunxi-fel 的相关命令
  • 文本分类场景下微调BERT
  • 类和对象的概述以及this指针的应用
  • Python基础—Python 中pip的8个必备命令
  • 力扣最热一百题——最大子数组和
  • 最新版 | 深入剖析SpringBoot3源码——分析自动装配原理(面试常考)
  • 超级 密码加密 解密 源码,支持表情,符号,数字,字母,加密
  • SpringBoot登录退出|苍穹外卖登录退出分析
  • yolov8 pt转onnx
  • Java并发:互斥锁,读写锁,Condition,StampedLock
  • 26 线性表 · 顺序表
  • 146. LRU 缓存
  • 11.2.软件系统分析与设计-数据库分析与设计
  • Rust使用之【宏】
  • C# 如何同时Ping多个IP地址
  • STM32 - 笔记4