[spring] 源码简析 如何解决循环依赖?
spring是创建实例的时候,是如何解决循环依赖的呢?
先来看一下isSingleton的实例getBean的整个流程:
步骤一
sharedInstance = getSingleton(name)
-
来获取缓存的单例实例
(来源两处,参见图中同色系框框,
一、单例创建完了会缓存一份singletonObjects;
二、创建过程中会缓存一份singletonFactories,创建完了删除) -
如果能够获取得到,则直接返回bean
-
如果获取不到,则走getSingleton来实例化单例(参见步骤二)
步骤二
getSingleton(name)
-
将自身加singletonsCurrentlyInCreation(正在创建的单例容器)中
-
执行createBean方法(步骤三)
-
将自身从singletonsCurrentlyInCreation(正在创建的单例容器)中移除
-
创建的单例实例加入到单例缓存singletonObjects中
步骤三
createBean方法
-
通过构造函数创建实例
-
如果是单例 & 允许循环依赖&
该bean在singletonsCurrentlyInCreation(正在创建的单例容器)中,则将上述创建的实例缓存到singletonFactories
-
populatBean依赖注入属性,如果属性是beanName,则调用getBean回到开头
假设spring没有去解决循环依赖的问题,假设新建如下两个类:
1@Component 2public class A { 3 4 @Autowired 5 private B b; 6 7 8 public A() { 9 System.out.println("A Constructor"); 10 } 11 12 @Override 13 public String toString() { 14 return "A{}"; 15 } 16} 1@Component 2public class B { 3 4 @Autowired 5 private A a; 6 7 8 public B() { 9 System.out.println("B Constructor"); 10 } 11 12 13 @Override 14 public String toString() { 15 return "B{}"; 16 } 17}
那么,在创建A的单例的过程中,需要依赖注入B,转而去创建B,B的创建过程中又要依赖注入A,此时A在beanFactory中不存在,转而又去创建A,这样会形成一种死循环。
问题的解决办法,就是要在创建过程中,有一条分支路线能够终止创建过程并且返回对象。
spring是怎么解决循环依赖的呢?
在创建一个单例的过程中,一旦通过构造函数创建了一个实例,就将中间过程的实例对象暂时缓存起来。
--> 创建A①
--> 执行到步骤三的第2步时,会将刚刚通过构造函数新建的实例缓存起来
--> 执行步骤三的第3步,依赖注入B,去创建B
--> B又依赖注入A,创建A
--> 步骤一中能直接从缓存singletonFactories获取到对象 return a
--> invoke b.setA(a)
--> return B
--> invoke a.setB(b)
--> return A
以上
更多源码分析,关注公众号👇👇👇
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 自定义通信协议——实现零拷贝文件传输
· Brainfly: 用 C# 类型系统构建 Brainfuck 编译器
· 智能桌面机器人:用.NET IoT库控制舵机并多方法播放表情
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· DeepSeek 全面指南,95% 的人都不知道的9个技巧(建议收藏)
· 自定义Ollama安装路径
· 本地部署DeepSeek
· 快速入门 DeepSeek-R1 大模型
· DeepSeekV3+Roo Code,智能编码好助手