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),发如今这里就要去建立咱们的对象,执行后置处理器,判断是否是有循环依赖,补充属性值等等操做web

当咱们点进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方法,将咱们须要的对象建立并放到容器中,在进行注入到咱们的属性中。
在这里插入图片描述
因为篇幅太长,接下来的流程就到下篇吧,其实不难发现太长的缘由是方法的调用太多,而我又不想漏掉每个方法的调用过程,让爱学习的小伙伴可以连贯起来。但愿你们多多评论。有帮助的话不要忘记点赞哦。spring