【面试题系列】高频面试题:Spring 如何解决循环依赖?

简介: Spring是通过递归的方式获取目标bean及其所依赖的bean的;Spring实例化一个bean的时候,是分两步进行的,首先实例化目标bean,然后为其注入属性。

 Spring整个解决循环依赖问题的实现思路如下图代码。对于整体过程,需要理解两点:

    • Spring是通过递归的方式获取目标bean及其所依赖的bean的;
    • Spring实例化一个bean的时候,是分两步进行的,首先实例化目标bean,然后为其注入属性。

    结合这两点,也就是说,Spring在实例化一个bean的时候,是首先递归的实例化其所依赖的所有bean,直到某个bean没有依赖其他bean,此时就会将该实例返回,然后反递归的将获取到的bean设置为各个上层bean的属性的。

    代码:

    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,也就是是否支持提前暴露半成品的bean
      boolean 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()方法尝试获取目标bean
        populateBean(beanName, mbd, instanceWrapper);
      } catch (Throwable ex) {
        // 省略...
      }
      return exposedObject;
    }

    image.gif


    相关文章
    |
    10天前
    |
    人工智能 Java Spring
    Spring Boot循环依赖的症状和解决方案
    Spring Boot循环依赖的症状和解决方案
    |
    16天前
    |
    Java Spring
    Spring面试题pro版-5
    Spring面试题pro版-5
    14 0
    |
    16天前
    |
    Java Spring
    Spring面试题pro版-4
    Spring面试题pro版-4
    14 0
    |
    16天前
    |
    XML Java 数据格式
    Spring面试题pro版-3
    Spring面试题pro版-3
    29 0
    |
    16天前
    |
    设计模式 Java 数据库
    Spring面试题系列-4
    Spring面试题系列-4
    19 1
    |
    6天前
    |
    存储 缓存 Java
    【Spring系列笔记】依赖注入,循环依赖以及三级缓存
    依赖注入: 是指通过外部配置,将依赖关系注入到对象中。依赖注入有四种主要方式:构造器注入、setter方法注入、接口注入以及注解注入。其中注解注入在开发中最为常见,因为其使用便捷以及可维护性强;构造器注入为官方推荐,可注入不可变对象以及解决循环依赖问题。本文基于依赖注入方式引出循环依赖以及三层缓存的底层原理,以及代码的实现方式。
    17 0
    |
    10天前
    |
    存储 缓存 Java
    【spring】06 循环依赖的分析与解决
    【spring】06 循环依赖的分析与解决
    6 1
    |
    16天前
    |
    设计模式 安全 Java
    Spring面试题pro版-6
    Spring面试题pro版-6
    16 0
    |
    16天前
    |
    缓存 Java Spring
    Spring面试题pro版-2
    Spring面试题pro版-2
    12 0
    |
    16天前
    |
    Java 数据库连接 API
    Spring面试题pro版-1
    Spring面试题pro版-1
    15 0