Spring解决循环依赖原理

问题描述

@Service
public GoodsService{
    @Autowared
    BillService billService
}
@Service
public BillService{
    @Autowared
    GoodsService goodsService
}
循环依赖

Spring bean大致的生命周期如下:

反射创建对象 -> 依赖注入 -> 初始化方法init -> aop等后置处理器 -> …

当执行GoodsService依赖注入时,该Service还未成为一个Spring bean(生命周期创建阶段还未完成),因此,无法将其注入BillService中(一个例子是,如果注入,则破坏了aop逻辑,因为此时的GoodsService还未配置aop代理,注入的是它本身)。

解决方案

三级缓存解决方案

三级缓存

获取bean流程

Spring获取Bean流程

源码

doGetBean():获取bean

protected <T> T doGetBean(
 final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
 throws BeansException {
    final String beanName = transformedBeanName(name);
    Object bean;

    // 第一次尝试获取单例bean
    // Eagerly check singleton cache for manually registered singletons.
    Object sharedInstance = getSingleton(beanName);
    if (sharedInstance != null && args == null) {
        ......
    }

    else {
        ......
            // Create bean instance.
            if (mbd.isSingleton()) {
                // 第二次尝试获取单例bean
                sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
                    @Override
                    public Object getObject() throws BeansException {
                        try {
                            return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {
                            // Explicitly remove instance from singleton cache: It might have been put there
                            // eagerly by the creation process, to allow for circular reference resolution.
                            // Also remove any beans that received a temporary reference to the bean.
                            destroySingleton(beanName);
                            throw ex;
                        }
                    }
                });
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            }
        ......
    }
    return (T) bean;
}

getSingleton():获取单例对象,在第一次尝试获取单例bean时调用

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
   // 尝试取一级缓存
   Object singletonObject = this.singletonObjects.get(beanName);
   // 如果该bean正在创建,isSingletonCurrentlyInCreation()为true,走如下分支
   if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
      synchronized (this.singletonObjects) {
         // 尝试取二级缓存
         singletonObject = this.earlySingletonObjects.get(beanName);
         // 如果二级缓存没有,则从三级缓存获取,并存入二级缓存
         if (singletonObject == null && allowEarlyReference) {
            ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
            if (singletonFactory != null) {
               singletonObject = singletonFactory.getObject();
               this.earlySingletonObjects.put(beanName, singletonObject);
               this.singletonFactories.remove(beanName);
            }
         }
      }
   }
   // 如果还未创建,则返回null
   return (singletonObject != NULL_OBJECT ? singletonObject : null);
}

doCreateBean() :创建bean,在第二次尝试获取单例bean时调用

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
 throws BeanCreationException {

    ......
    // Eagerly cache singletons to be able to resolve circular references
    // even when triggered by lifecycle interfaces like BeanFactoryAware.
    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
            isSingletonCurrentlyInCreation(beanName));
    if (earlySingletonExposure) {
        if (logger.isDebugEnabled()) {
            logger.debug("Eagerly caching bean '" + beanName +
                    "' to allow for resolving potential circular references");
        }
        // 加入三级缓存
        addSingletonFactory(beanName, new ObjectFactory<Object>() {
            @Override
            public Object getObject() throws BeansException {
                return getEarlyBeanReference(beanName, mbd, bean);
            }
        });
    }
    // Initialize the bean instance.
   Object exposedObject = bean;
   try {
      // 依赖注入
      populateBean(beanName, mbd, instanceWrapper);
      if (exposedObject != null) {
         // 初始化方法
         exposedObject = initializeBean(beanName, exposedObject, mbd);
      }
   }
   catch (Throwable ex) {
      if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
         throw (BeanCreationException) ex;
      }
      else {
         throw new BeanCreationException(
               mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
      }
   }

   // 这里检查是否提前暴露了bean
   // 如果允许循环依赖,走下面分支
   if (earlySingletonExposure) {
      // 这里只会查一级缓存和二级缓存,一级缓存肯定为空,若存在循环依赖,则返回二级缓存的对象
      Object earlySingletonReference = getSingleton(beanName, false);
      // 如果二级缓存查到了对象,说明存在循环依赖,走下面分支
      if (earlySingletonReference != null) {
         // 如果此时二级缓存的对象与exposedObject相等,说明提前暴露的bean对象是安全的
         if (exposedObject == bean) {
            exposedObject = earlySingletonReference;
         }
         // 否则,证明exposedObject被进行了其他代理(可能是init阶段),前面提前暴露时没有捕捉到,证明提前暴露是不安全的
         // 如果还有依赖它的bean,说明bean有可能被暴露出去了,走下面分支
         else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
            String[] dependentBeans = getDependentBeans(beanName);
            Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
            // 遍历所有依赖它的Bean
            for (String dependentBean : dependentBeans) {
               // 如果此时有依赖它的bean被成功创建了,证明bean真的被暴露出去了,抛出异常
               // 原因是因为getEarlyBeanReference()方法不一定能处理所有的代理情形
               if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                  actualDependentBeans.add(dependentBean);
               }
            }
            if (!actualDependentBeans.isEmpty()) {
               throw new BeanCurrentlyInCreationException(beanName,
                     "Bean with name '" + beanName + "' has been injected into other beans [" +
                     StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                     "] in its raw version as part of a circular reference, but has eventually been " +
                     "wrapped. This means that said other beans do not use the final version of the " +
                     "bean. This is often the result of over-eager type matching - consider using " +
                     "'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
            }
         }
      }
   }

   return exposedObject;
}

getEarlyBeanReference():三级缓存的实例获取实现方法:

protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
    Object exposedObject = bean;
    if (bean != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            // 获取后置处理器,提前完成aop等逻辑
            // 注意,spring扩展点很多,此处可能不能处理所有扩展点中的代理逻辑
            if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
                SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
                exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
                if (exposedObject == null) {
                    return null;
                }
            }
        }
    }
    return exposedObject;
}

总结

使用三级缓存,各级缓存作用如下:

  • 三级缓存(singletonFactories):将aop等后置处理器包装到工厂中
  • 二级缓存(earlySingletonObjects):存放三级缓存中生成的对象,让三级缓存的对象生成方法只执行一次,保证对象是单例的
  • 一级缓存(singletonObjects):存放所有已经初始化完成的bean,保证bean是单例的
下一篇