循环上传导致oom_Spring 源码学习(五) 循环依赖

还记得上一篇笔记,在 bean 加载流程,在创建过程中,出现了依赖循环的监测,如果出现了这个循环依赖,而没有解决的话,代码中将会报错,然后 Spring 容器初始化失败。

由于感觉循环依赖是个比较独立的知识点,所以我将它的分析单独写一篇笔记,来看下什么是循环依赖和如何解决它。


Table of Contents generated with DocToc

  • 前言
  • 循环依赖构造器循环依赖property 范围的依赖处理setter 循环依赖代码分析解决场景结合关键代码梳理流程创建原始 beanaddSingleFactorypopulateBean 填充属性getSingleton
  • 总结
  • 参考资料

循环依赖

循环依赖就是循环引用,就是两个或者多个 bean 相互之间的持有对方,最后形成一个环。例如 A 引用了 B,B 引用了 C,C 引用了 A。

可以参照下图理解(图中展示的类的互相依赖,但循环调用指的是方法之间的环调用,下面代码例子会展示方法环调用):

2aea867e481be3313d338d2f162864ee.png

如果学过数据库的同学,可以将循环依赖简单的理解为死锁,互相持有对方的资源,形成一个环,然后不释放资源,导致死锁发生。

在循环调用中,除非出现终结条件,否则将会无限循环,最后导致内存溢出错误。(我也遇到过一次 OOM,也是无限循环导致的)


书中的例子是用了三个类进行环调用,我为了简单理解和演示,使用了两个类进行环调用:

在 Spring 中,循环依赖分为以下三种情况:

构造器循环依赖

9c3aab66878bbf32951172dc6ebf712d.png

通过上图的配置方法,在初始化的时候就会抛出 BeanCurrentlyInCreationException 异常

public static void main(String[] args) {// 报错原因: Requested bean is currently in creation: Is there an unresolvable circular reference?ApplicationContext context = new ClassPathXmlApplicationContext("circle/circle.xml");}

从上一篇笔记中知道,Spring 容器将每一个正在创建的 bean 标识符放入一个 “当前创建 bean 池(prototypesCurrentlyInCreation)” 中,bean 标识符在创建过程中将一直保持在这个池中。

检测循环依赖的方法:

分析上面的例子,在实例化 circleA 时,将自己 A 放入池中,由于依赖了 circleB,于是去实例化 circleB,B 也放入池中,由于依赖了 A,接着想要实例化 A,发现在创建 bean 过程中发现自己已经在 “当前创建 bean” 里时,于是就会抛出 BeanCurrentlyInCreationException 异常。

如图中展示,这种通过构造器注入的循环依赖,是无法解决的


property 范围的依赖处理

property 原型属于一种作用域,所以首先来了解一下作用域 scope 的概念:

在 S

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值