Spring 是如何 解决循环依赖的问题

初次遇到这个问题是在开发中,但是没有深究,前一阵参加面试就被问到这个问题,当时真是非常后悔,怎么没有好好研究一下呢。现在来亡羊补牢吧。

循环依赖的定义:

循环依赖就是循环引用,就是两个或多个bean 相互之间的持有对方,比如CircleA 引用CircleB , CircleB 引用CircleC, CircleC 引用CircleA ,则它们最终反映为一个环。

1 .构造器循环依赖
表示通过构造器注入构成的循环依赖, 此依赖是无法解决的,只能抛出BeanCurrentlylnCreationException异常表示循环依赖。
如在创建TestA 类时, 构造器需要TestB 类,那将去创建TestB , 在创建TestB 类时又发现需要TestC 类, 则又去创建TestC , 最终在创建TestC 时发现又需要TestA ,从而形成一个环,没办法创建。
Spring 容器将每一个正在创建的bean 标识符放在一个“当前创建bean 池”中, bean 标识符:在创建过程中将一直保持在这个池中,因此如果在创建bean 过程中发现自己已经在“当前创建bean 池” 里时,将抛出BeanCurrentlylnCreationException 异常表示循环依赖;而对于创建完毕的bean 将从“ 当前创建bean 池”中清除掉。

 

2. setter 循环依赖

表示通过setter 注入方式构成的循环依赖。对于setter 注入造成的依赖是通过Spring 容器提前暴露刚完成构造器注入但未完成其他步骤(如setter 注入)的bean 来完成的,而且只能解决单例作用域的bean 循环依赖。通过提前暴露一个单例工厂方法,从而使其他bean 能引用到该bean 
具体步骤如下。
l. Spring 容器创建单例“testA ” bean ,首先根据元参构造器创建bean ,并暴露一个“0bjectFactory”用于返回一个提前暴露一个创建中的bean ,并将“testA”标识符放到“当前创建bean 池”, 然后进行setter 注入“testB ” 。
2. Spring 容器创建单例“ testB ” bean ,首先根据无参构造器创建bean ,并暴露一个“ ObjectFactory”用于返回一个提前暴露一个创建中的bean ,并将“testB”标识符放到“当前创建bean 池”,然后进行setter 注入“circle ” 。
3. Spring 容器创建单例“ testC ” bean ,首先根据元参构造器创建bean ,并暴露一个“ ObjectFactory”用于返回一个提前暴露一个创建中的bean ,并将“testC”标识符放到“当前创建bean 池”,然后进行setter 注入“testA” 。进行注入“testA”时由于提前暴露了“ObjectFactory”工厂,从而使用它返回提前暴露一个创建中的bean 。
4. 最后在依赖注入“testB ”和“testA ”,完成setter 注入。

3.prototype 范围的依赖处理
对于“prototype”作用域bean, Spring 容器无法完成依赖注入,因为Spring 容器不进行缓存“prototype”作用域的bean ,因此无法提前暴露一个创建中的bean.

 

参考:《Spring 源码深度解析》(第二版)

https://www.iflym.com/index.php/code/201208280001.html 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值