Spring如何解决循环依赖问题?让我们来一探究竟!!!

1、背景

        最近自己在尝试写一个简易的IOC容器,让自己更好的理解Spring的IOC原理。

        当然我这里并没有参考任何Spring的源码(之后肯定会的!!!),而是参考敖丙写的文章进行的学习(链接放在文末)

        当我实现了简易的实例化、依赖注入功能后,突然想到了循环依赖问题,久闻大名,一直未去深入了解,于是决定在今天去揭开Spring解决循环依赖方案的面纱,一探究竟!!!

2、循环依赖是什么?

        简单来说,循环依赖就是两个Bean对象的属性值互相为对方,再结合Spring中Bean的生命周期就非常好理解了。这里不过多展开,放一张图片让大家看一下(图源放在文末)

         如果还是不能理解,我文末会放一个链接,大家可以去看一下,同时也是上面的图源链接。

3、Spring是怎么发现循环依赖的?

        没错,想要解决循环依赖,那就得先发现循环依赖,这里需要结合Spring两个的行为。

        (1)Spring在创建bean之前会先去二级缓存中查找是否存在对应的bean

        (2)Spring会把实例化完成,但还未完成依赖注入的bean放入的二级缓存中

        结合以上两个行为,当Spring在创建bean之前,在二级缓存中查找到存在对应的bean,那么就代表存在循环依赖了。

 4、Spring是怎么解决循环依赖的?

        循环依赖是因为依赖注入阶段无法获取到只完成了实例化的bean对象,所以Spring就加了一个二级缓存,用于存放只完成了实例化的bean对象,提前暴露bean。

        当发生循环原来时,Spring会把只完成实例化,但还未完成依赖注入的原始bean注入到目标bean中,以此来解决循环依赖。

        PS:以上方案只能解决字段注入方式产生的循环依赖,当bean之间的循环依赖是构造器方法方式产生的时,此方案是无法解决的。

5、代码实现

        以下是我自己的IOC容器中,解决循环依赖的二级缓存应用,非常简单,供大家参考。

/**
 * 创建Bean并填充属性
 * @param clazz
 * @return
 */
private static Object doCreateBean(String beanName,Class<?> clazz) throws InstantiationException, IllegalAccessException {
    // 1、使用无参构造方法实例化Bean
    Object bean = clazz.newInstance();
    // 1.1、把(完成实例化,但未属性赋值的bean)放入二级缓存,提前暴露bean
    // 这一步,是为了解决循环依赖问题,也用于发现循环依赖问题
    beanCacheMap.put(beanName,bean);
    // 2、为bean填充属性(依赖注入)
    populateBean(bean,clazz);
    // 3、当前Bean完成依赖注入阶段,移除二级缓存中的bean
    // 保证循环依赖的发现机制正常运转
    beanCacheMap.remove(beanName);
    return bean;
}

6、总结

        Spring的设计总是让我惊叹,简直是编程界的艺术品,之后也计划对Spring进行深入的学习,期待有更多的内容分享给大家!!!加油加油!!!

文末链接

浅入浅出Spring架构设计 - 掘金 (juejin.cn)

浅谈 Spring 如何解决 Bean 的循环依赖问题 - 掘金 (juejin.cn)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值