什么是Spring中的循环依赖?
循环依赖是指两个或者多个bean互相依赖对方,从而形成一个闭环。例如:Bean A依赖于Bean B,而Bean B又依赖于Bean A。可能会导致Spring在尝试创建这些bean实例时出现问题,因为他们互相等待对方被创建,最终导致应用程序无法启动。
Spring是如何发现这种循环依赖的问题的呢?
通过依赖图来检测和发现循环依赖问题。如下步骤:
1 Bean的创建过程
Spring容器在启动时,会扫描配置文件(appliactionContext.xml)或者注解定义的bean,并且尝试创建这些bean的实例。创建bean实例的过程如下
- 实例化:创建bean的实例。
- 属性填充:为bean注入依赖其他的bean。
- 初始化:执行自定义的初始化方法。
2 依赖注入过程
在属性填充阶段,Spring会为每个bean注入他所依赖的bean。在这个过程中,Spring会跟踪哪些bean正在被创建,以便检测循环依赖。
3 循环依赖检测机制
Spring通过一个名为“DefaultSingletonBeanRegistry”的类来跟踪单例bean的创建状态。该类维护了三个主要的缓存来管理bean的创建过程。
- singletonObjects:一级缓存(存储完全初始化好的bean)
- earlySingletonObjects:二级缓存(存储早期暴露的单例bean,用于解决循环依赖)
- singletonFactories:三级缓存(存储用于创建bean实例的工厂)
具体的检测步骤
实例化阶段
当Spring开始实例化一个bean时,它会将这个bean标记为正在创建。这一步是通过将bean名称添加到一个“正在创建中的bean”集合(‘singletonCurrentlyInCreaontion’)中来实现的。
属性填充阶段
在属性填充阶段,Sping会为该bean注入其依赖的其他的bean。此时Spring会检查这个“其他的bean”是否已经在创建过程中。
- 如果依赖的bean已经在创建中,Spring会检测到循环依赖,并根据不同的注入方式采取不同的处理方式。
- 如果是构造函数注入,Spring会抛出‘BeanCurrentlyInCreationException’,因为无法解决构造函数中注入的循环依赖。
- 如果是Setter注入,Spring会从‘earlySingletonObjects’或‘singletonFactories’中获取依赖的bean,提前暴露一个部分创建的bean引用来解决循环依赖。
举例
如Bean A和Bean B循环依赖
@Component
public class A {
@Autowired
private B b;
public A() {
System.out.println("A is created");
}
}
@Component
public class B {
@Autowired
private A a;
public B() {
System.out.println("B is created");
}
}
Spring的依赖注入过程:
1 实例化Bean A
- 将Bean A 标记为正在创建,并添加到‘singletonCurrentlyInCreation’集合中。
- 实例化Bean A,并将其放入到三级缓存‘singletonFactories’中。(三级缓存存放的是创建实例化的bean工厂)
2 填充Bean A的属性
- 此时发现Bean A依赖Bean B ,于是开始创建Bean B。
- 将Bean B标记为正在创建,并放入到‘singletonCurrentlyInCreation’集合中。
- 实例化Bean B,并将其放入到三级缓存‘singletonFactories’中。
3 填充Bean B的属性
- 发现Bean B依赖于Bean A 。此时,检查到Bean A 已经在创建过程中,因此发现了循环依赖。
- 由于是Setter方法注入,Spring会从三级缓存‘singletonFactories’中获取一个部分创建的Bean A实例,提前暴露出来,放入二级缓存‘earlySingletonObjects’中。
- 使用这个部分创建出来的Bean A实例 来填充Bean B的属性。
4 完成Bean B的创建
- Bean B中的所有属性填充完毕后,Spring将Bean B的实例从三级缓存‘singletonFactories’中移到一级缓存‘singletonObjects’完全初始化好的bean中。
5 回到Bean A的创建
- 继续为Bean A填充属性,此时可以从一级缓存‘singletonObejcts’中获取到完整的Bean B实例。
- 完成Bean A的创建,并将其从三级缓存‘singletonFactories’中移到一级缓存‘singletonObjects’中。
1.本站内容仅供参考,不作为任何法律依据。用户在使用本站内容时,应自行判断其真实性、准确性和完整性,并承担相应风险。
2.本站部分内容来源于互联网,仅用于交流学习研究知识,若侵犯了您的合法权益,请及时邮件或站内私信与本站联系,我们将尽快予以处理。
3.本文采用知识共享 署名4.0国际许可协议 [BY-NC-SA] 进行授权
4.根据《计算机软件保护条例》第十七条规定“为了学习和研究软件内含的设计思想和原理,通过安装、显示、传输或者存储软件等方式使用软件的,可以不经软件著作权人许可,不向其支付报酬。”您需知晓本站所有内容资源均来源于网络,仅供用户交流学习与研究使用,版权归属原版权方所有,版权争议与本站无关,用户本人下载后不能用作商业或非法用途,需在24个小时之内从您的电脑中彻底删除上述内容,否则后果均由用户承担责任;如果您访问和下载此文件,表示您同意只将此文件用于参考、学习而非其他用途,否则一切后果请您自行承担,如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。
5.本站是非经营性个人站点,所有软件信息均来自网络,所有资源仅供学习参考研究目的,并不贩卖软件,不存在任何商业目的及用途
暂无评论内容