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

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

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

你可能感兴趣的:(spring)