Spring揭秘日志——番外(Spring解决循环依赖)

Spring循环依赖

上次在拜读Spring揭秘的第二章时,依赖注入这个问题是SpringIOC的一步核心操作,但是在依赖注入的时候也发现了一个问题,在依赖注入的时候,如果Bean之间的属性引用产生了互相引用,那么在加载的时候就会出现循环依赖的经典Spring问题。(创建新的A时,发现要注入原型字段B,又创建新的B发现要注入原型字段A…)

Spring内部对于循环依赖是做出了一些解决方案的,首先肯定会帮你报个错,就像递归没有退出条件一样系统会抛出StackOverflow错误一样。Spring在遇到了这种情况时会抛出BeanCurrentlyInCreationException。

那么我们还是先回顾一下之前Spring的三种依赖注入:构造器注入、Setter注入、接口注入(该方式基本没人用了)。在官方文档中不允许基于构造器的循环依赖。在Spring2.5中就有了@Autowired自动注入。

那么Spring如何解决的循环依赖这个问题?我拜读了各位大佬的见解,很多都是说的使用一个三级缓存,这个三级缓存其实就是三个Map(singletonObjects(单例池容器);singletonFactories(映射创建Bean的原始工厂); earlySingletonObjects(初始化Bean))。

下面就基于IOC的Bean初始化的流程中的一部分进行Spring三级缓存处理循环依赖的说明(过段时间会写一篇IOC注入Bean的源码流程)先记住一个Bean注入的流程为:getSingleton()->doCreateBean()->populateBean()->addSingleton()

A注入时:
  1. 在doCreateBean()中会将A的工厂缓存到singletonObjects()这个Map中
  2. 之后进入populateBean()中加载A中的属性,发现A中有引用B这时开始注入B
  3. B重复1、2步骤
  4. 之后B来到了populateBean()中加载属性,发现B中有引用A,这时开始注入A
  5. A在getSingleton时发现之前有A工厂在singletonFactory中有缓存,于是就利用工厂A创建A到earlySingletonObjects中,之后B就在addSingleton中拿到A的属性,进入addSingleton()方法中,之后就注入了B。
  6. 之后A拿到了B就进入addSingleton,完成了A的注入。
总结:如果A、B注入一直走的是getSingleton()->doCreateBean()->populateBean()就会产生循环依赖,而通过三级缓存时就会在第一次循环的开始直接调用缓存的A工厂来把A进行了早期初始化,并且给了B,之后就正常进行,避免了循环依赖的问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值