spring的循环依赖(3)循环依赖的解决(源码级一)

最近由于项目比较忙,一时脱不开身总结学习的spring。加上疫情又耽误了一些时间,本次更新就延后了很多。相信爱学习的小伙伴们都在其他博客上找到了spring是怎么解决循环依赖的问题了吧。作者近期也总结了一下,还是希望小伙伴们帮作者看看有木有什么漏洞不到位的地方,欢迎吐槽。
上篇文章我们详细介绍了循环依赖的场景,那么spring是怎么解决的呢?让我们一步一步的解开他神秘的面纱吧。
我们就从getBean(String name)开始说起,至于怎么运行到这里的,请在网上看其他文章
getBean中调用了doGetBean
在doGetBean中我们首先先调用getSingleton()这里是一个参数的方法,我们先去看看缓存中有没有我们要创建的bean,我们第一次创建,显然是没有
在这里插入图片描述
接下来我们就会调用getSingleton(String A, ObjectFactory<?> singletonFactory)
和上面的方法不一样!!!这里是重写了上面一个参数的方法,第二个参数为工厂对象在这里插入图片描述
首先我们点进getSingleton(String A, ObjectFactory<?> singletonFactory)这个方法里可以看到beforeSingletonCreation(beanName);
在这里插入图片描述
让我们再点进beforeSingletonCreation(beanName)看一下,原来是把我们要创建得对象得名字放到了一个交singletonsCurrentlyInCreation得集合中。请记住这里
在这里插入图片描述
接下来我们在看getSingleton(String A, ObjectFactory<?> singletonFactory),其中ObjectFactory<?> singletonFactory是一个代码块,里面包含了一个createBean(beanName, mbd, args)方法
在这里插入图片描述
这个代码块是在我们getSingleton(String A, ObjectFactory<?> singletonFactory)这个方法执行过程中调用的
在这里插入图片描述
我们在点进createBean(beanName, mbd, args),发现调用了doCreateBean(beanName, mbdToUse, args)
在这里插入图片描述
我们在点进doCreateBean(beanName, mbdToUse, args),发现在这里就要去创建我们的对象,执行后置处理器,判断是不是有循环依赖,补充属性值等等操作

当我们点进isSingletonCurrentlyInCreation()这个方法就会发现里面只是singletonsCurrentlyInCreation集合中是否包含我们当前要创建的实例返回true,allowCircularReferences默认是true,我们创建的实例又是单例的,所以earlySingletonExposure就是true。这也能说明我们spring默认是允许进行循环依赖的。
接下来就会执行addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));有两个参数,一个是实例名,另一个也是代码块。
在这里插入图片描述
让我们点进addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
我们前面没有说过往集合singletonObjects添加多实例,所以说肯定是不包含的。那么就要去singletonFactories和registeredSingletons添加我们的实例,注意我们这里并没有执行我们的代码块,而是将他放在singletonFactories集合中。为什么要放在集合中而不执行?后面我们会讲到。为什么又要从earlySingletonObjects中移除呢?后面也会讲到
在这里插入图片描述
接下来我们回到主方法来,就是要执行populateBean(beanName, mbd, instanceWrapper);这个方法就是给我们的属性注入值,我们说的循环依赖就是发生在这里。
在这里插入图片描述
点进去populateBean(beanName, mbd, instanceWrapper);我们可以看到在注入的时候分为byName和byType两种方式。我们这边只看byType
在这里插入图片描述
我们点进autowireByType(beanName, mbd, bw, newPvs);发现调用了resolveDependency(desc, beanName, autowiredBeanNames, converter);
在这里插入图片描述
我们在点进resolveDependency(desc, beanName, autowiredBeanNames, converter);发现调用doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
在这里插入图片描述
我们在点进doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
发现调用descriptor.resolveCandidate(autowiredBeanName, type, this);
在这里插入图片描述
当我们点进descriptor.resolveCandidate(autowiredBeanName, type, this);就会惊奇的发现调用了beanFactory.getBean(beanName);这个getBean方法。这不是我们的入口吗?没错就是他。所以我们spring在创建对象的时候如果遇到容器中没有的对象需要注入的话,最终会再次调用getBean方法,将我们需要的对象创建并放到容器中,在进行注入到我们的属性中。
在这里插入图片描述
由于篇幅太长,接下来的流程就到下篇吧,其实不难发现太长的原因是方法的调用太多,而我又不想漏掉每一个方法的调用过程,让爱学习的小伙伴能够连贯起来。希望大家多多评论。有帮助的话不要忘记点赞哦。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值