跳槽那些事儿@面试问你Spring如何解决循环依赖的时候,不要一脸懵逼了!( 三 )

这里我们会存在一个问题就是A的半成品实例是如何实例化的 , 然后是如何将其封装为一个ObjectFactory类型的对象 , 并且将其放到上面的singletonFactories属性中的 。 这主要是在前面的第二个getSingleton()方法中 , 其最终会通过其传入的第二个参数 , 从而调用createBean()方法 , 该方法的最终调用是委托给了另一个doCreateBean()方法进行的 , 这里面有如下一段代码:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)throws BeanCreationException {// 实例化当前尝试获取的bean对象 , 比如A对象和B对象都是在这里实例化的BeanWrapper instanceWrapper = null;if (mbd.isSingleton()) {instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);}if (instanceWrapper == null) {instanceWrapper = createBeanInstance(beanName, mbd, args);}// 判断Spring是否配置了支持提前暴露目标bean , 也就是是否支持提前暴露半成品的beanboolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences&& isSingletonCurrentlyInCreation(beanName));if (earlySingletonExposure) {// 如果支持 , 这里就会将当前生成的半成品的bean放到singletonFactories中 , 这个singletonFactories// 就是前面第一个getSingleton()方法中所使用到的singletonFactories属性 , 也就是说 , 这里就是// 封装半成品的bean的地方 。 而这里的getEarlyBeanReference()本质上是直接将放入的第三个参数 , 也就是// 目标bean直接返回addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));}try {// 在初始化实例之后 , 这里就是判断当前bean是否依赖了其他的bean , 如果依赖了 ,// 就会递归的调用getBean()方法尝试获取目标beanpopulateBean(beanName, mbd, instanceWrapper);} catch (Throwable ex) {// 省略...}return exposedObject;} 到这里 , Spring整个解决循环依赖问题的实现思路已经比较清楚了 。 对于整体过程 , 读者朋友只要理解两点:

  • Spring是通过递归的方式获取目标bean及其所依赖的bean的;
  • Spring实例化一个bean的时候 , 是分两步进行的 , 首先实例化目标bean , 然后为其注入属性 。
结合这两点 , 也就是说 , Spring在实例化一个bean的时候 , 是首先递归的实例化其所依赖的所有bean , 直到某个bean没有依赖其他bean , 此时就会将该实例返回 , 然后反递归的将获取到的bean设置为各个上层bean的属性的 。
【跳槽那些事儿@面试问你Spring如何解决循环依赖的时候,不要一脸懵逼了!】对了 , 在这里说一下 , 我目前是在职Java开发 , 如果你现在正在学习Java , 了解Java , 渴望成为一名合格的Java开发工程师 , 在入门学习Java的过程当中缺乏基础入门的视频教程 , 可以关注并私信我:01 。 获取 。 我这里有最新的Java基础全套视频教程 。


推荐阅读