Bean的循环依赖

什么是循环依赖?

Bean的循环依赖指的是在Spring应用上下文中,两个或多个bean互相依赖,形成一个闭环,导致Spring在实例化这些bean时遇到的问题。具体来说,当尝试初始化一个bean A 时,发现它依赖于另一个bean B,而在尝试初始化bean B 时,又发现它反过来依赖于bean A,这就构成了一个循环依赖。

假设有两个类A和B,A依赖于B,B依赖于A

三级缓存

Spring容器提供了相应的方案来解决Bean的循环依赖问题

Spring容器维护了三个级别的缓存来管理Bean的生命周期状态。

一级缓存用于存储已经初始化完成的Bean实例以及代理

二级缓存用于存储半成品的Bean——已经实例化但是没有依赖注入(二级缓存的作用就是避免多次调用工厂导致多例的产生

三级缓存用于存储Bean和代理的工厂(用于创建对象)

提前暴露未完成的Bean

在Bean实例化过程中,Spring容器采用一种称为“提前曝光”(Early Exposure)的策略。当容器开始创建一个Bean(假设为Bean A),但在构造函数注入或直接字段注入之前,它会将一个未完全初始化的Bean A的引用(一个半成品Bean)提前放置到一个特殊的缓存(通常是二级缓存,即earlySingletonObjects)中。这意味着即使Bean A还没有完成所有的依赖注入,它的一个引用已经被创建并且可以被其他正在初始化的Bean(比如Bean B)所访问。

依赖注入的时机

当一个Bean(如Bean B)依赖于另一个正在创建的Bean(Bean A)时,Spring会检查是否已经有Bean A的半成品引用存在于二级缓存中。如果存在,就直接使用这个半成品引用,而不是等待Bean A完全初始化完成,从而打破了循环依赖的链条。之后,Spring会继续完成Bean A的依赖注入,并将其从二级缓存移动到一级缓存,表示它已经完全初始化好了。

需要注意的点:

  • 构造器循环依赖无法解决:如果循环依赖是通过构造器注入形成的,Spring无法解决这种依赖,因为构造器注入必须在对象实例化时完成。
  • 非singleton作用域的Bean不处理循环依赖:对于prototype作用域的Bean,Spring不会处理循环依赖问题,因为每个请求都会创建一个新的实例。
  • @Lazy注解:使用@Lazy注解可以在一定程度上缓解循环依赖问题,因为它推迟了依赖Bean的初始化,直到真正需要使用它的时候。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值