Spring如何解决循环依赖问题

首先是ioc的创建流程简图

初始化对象时的循环依赖问题

这个问题出现在上图applicationContext.refresh()方法中,再生成Bean对象时出现的

@Override
public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
      // Prepare this context for refreshing.
      prepareRefresh();

      // Tell the subclass to refresh the internal bean factory.
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      // Prepare the bean factory for use in this context.
      //准备BeanFactory的前置工作
      prepareBeanFactory(beanFactory);

      try {
         // Allows post-processing of the bean factory in context subclasses.
         //生产BeanFactoryPostProcess对象
         postProcessBeanFactory(beanFactory);

         // Invoke factory processors registered as beans in the context.
         //执行BeanFactoryPostProcess对象的方法处理BeanDefintion的信息
         invokeBeanFactoryPostProcessors(beanFactory);

         // Register bean processors that intercept bean creation.
         //准备BeanPostProcessor对象
         registerBeanPostProcessors(beanFactory);

         // Initialize message source for this context.
         //国际化
         initMessageSource();

         // Initialize event multicaster for this context.
         //准备事件监听
         initApplicationEventMulticaster(); 

         // Initialize other special beans in specific context subclasses.
         onRefresh();

         // Check for listener beans and register them.
         //注册监听器
         registerListeners();

         // Instantiate all remaining (non-lazy-init) singletons.
         //生产Bean
         finishBeanFactoryInitialization(beanFactory);  

         // Last step: publish corresponding event.
         finishRefresh();
      }
      ...
   }
}
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
  ...
   // Instantiate all remaining (non-lazy-init) singletons.
   beanFactory.preInstantiateSingletons();
}

然后循环BeanDefintion的信息getBean(创建Bean)

@Override
public void preInstantiateSingletons() throws BeansException {
  ...
   // Trigger initialization of all non-lazy singleton beans...
   for (String beanName : beanNames) {
      RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
      if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
         if (isFactoryBean(beanName)) {
            Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
            if (bean instanceof FactoryBean) {
               final FactoryBean<?> factory = (FactoryBean<?>) bean;
               boolean isEagerInit;
               if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                  isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
                              ((SmartFactoryBean<?>) factory)::isEagerInit,
                        getAccessControlContext());
               }
               else {
                  isEagerInit = (factory instanceof SmartFactoryBean &&
                        ((SmartFactoryBean<?>) factory).isEagerInit());
               }
               if (isEagerInit) {
                  getBean(beanName);
               }
            }
         }
         else {
            getBean(beanName);
         }
      }
   }
 ...
}

doGetBean是核心

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
      @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

   final String beanName = transformedBeanName(name);
   Object bean;

   // Eagerly check singleton cache for manually registered singletons.
   Object sharedInstance = getSingleton(beanName);
   	...
         // Create bean instance.
         if (mbd.isSingleton()) {
            sharedInstance = getSingleton(beanName, () -> {
               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);
         }
        ...
}

createBean包含了核心doCreateBean方法

@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {
  ...
   try {
      Object beanInstance = doCreateBean(beanName, mbdToUse, args);
      if (logger.isDebugEnabled()) {
         logger.debug("Finished creating instance of bean '" + beanName + "'");
      }
      return beanInstance;
   }
   ...
}

此时完成对a的实例化,开始进行a的初始化

此时{

一级缓存:null

二级缓存:null

三级缓存:{A的beanName:获取A对象二级缓存对象的方法}

})

addSingletonFactory将数据放到三级缓存中

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

   // Instantiate the bean.
   ...

   // 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) {
      ...
      addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));//将获取二级缓存方法的匿名内部类放入三级缓存
   }

   // Initialize the bean instance.
   Object exposedObject = bean;
   try {
      populateBean(beanName, mbd, instanceWrapper); //初始化Bean 非常重要!!!
      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);
      }
   }

   ...

   // Register bean as disposable.
   ...

   return exposedObject;
}

populateBean对A实例化的过程中发现没有B对象 所以开始对B进行doCreateBean

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
   ...
   if (pvs != null) {
      applyPropertyValues(beanName, mbd, bw, pvs);
   }
}
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
   ...
   // Create a deep copy, resolving any references for values.
   List<PropertyValue> deepCopy = new ArrayList<>(original.size());
   boolean resolveNecessary = false;
   for (PropertyValue pv : original) {
      if (pv.isConverted()) {
         deepCopy.add(pv);
      }
      else {
         String propertyName = pv.getName();
         Object originalValue = pv.getValue();
         Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);//处理数据
         
   ...
}
public Object resolveValueIfNecessary(Object argName, @Nullable Object value) {
   // We must check each value to see whether it requires a runtime reference
   // to another bean to be resolved.
   if (value instanceof RuntimeBeanReference) {
      RuntimeBeanReference ref = (RuntimeBeanReference) value;
      return resolveReference(argName, ref);
   }
   ...
}
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
   try {
      Object bean;
      String refName = ref.getBeanName();
      refName = String.valueOf(doEvaluate(refName));
      if (ref.isToParent()) {
         if (this.beanFactory.getParentBeanFactory() == null) {
            throw new BeanCreationException(
                  this.beanDefinition.getResourceDescription(), this.beanName,
                  "Can't resolve reference to bean '" + refName +
                  "' in parent factory: no parent factory available");
         }
         bean = this.beanFactory.getParentBeanFactory().getBean(refName);
      }
      else {
         bean = this.beanFactory.getBean(refName);//通过getBean创建BeanB
         this.beanFactory.registerDependentBean(refName, this.beanName);
      }
      if (bean instanceof NullBean) {
         bean = null;
      }
      return bean;
   }
   catch (BeansException ex) {
      throw new BeanCreationException(
            this.beanDefinition.getResourceDescription(), this.beanName,
            "Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, ex);
   }
}

再次回到doCreateBean方法将B实例化

此时{

一级缓存:null

二级缓存:null

三级缓存:{A的beanName:获取A对象二级缓存对象的方法} {B的beanName:获取B对象二级缓存对象的方法}

})

再次回到B的初始化中 此时已经可以获取到A的实例了 将此RuntimeBeanReference分配给B的实例

private Object resolveReference(Object argName, RuntimeBeanReference ref) {
   try {
      Object bean;
      String refName = ref.getBeanName();
      refName = String.valueOf(doEvaluate(refName));
      if (ref.isToParent()) {
         ...
      }
      else {
         bean = this.beanFactory.getBean(refName); //此时再getBean时,getSingleton已经能拿到A实例了
         this.beanFactory.registerDependentBean(refName, this.beanName);
      }
      if (bean instanceof NullBean) {
         bean = null;
      }
      return bean;
   }
   ...
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
   Object singletonObject = this.singletonObjects.get(beanName); //先找一级缓存有没有A
   if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
      synchronized (this.singletonObjects) {
         singletonObject = this.earlySingletonObjects.get(beanName);//再找二级缓存有没有A
         if (singletonObject == null && allowEarlyReference) {  //此时这里A对象正在创建中
            ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);//发现三级缓存中有A
            if (singletonFactory != null) { //将A对象放入二级缓存中singletonFactory.getObject()调用匿名方法,即 getEarlyBeanReference()
               singletonObject = singletonFactory.getObject();
               this.earlySingletonObjects.put(beanName, singletonObject);
               this.singletonFactories.remove(beanName);
            }
         }
      }
   }
   return singletonObject;
}

此时{

一级缓存:null

二级缓存:{A的beanName:BeanA}

三级缓存:{B的beanName:获取B对象二级缓存对象的方法}

})

doCreateBean结束之后执行addSingleton()将B放到一级缓存中

此时{

一级缓存:{B的beanName:BeanB}

二级缓存:{A的beanName:BeanA}

三级缓存:null

})

此时B完成了createBean的动作最后赋值给了A的实例,此时A也回到这里,执行addSingleton将A实例放到一级缓存中

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
   Assert.notNull(beanName, "Bean name must not be null");
   synchronized (this.singletonObjects) {
      Object singletonObject = this.singletonObjects.get(beanName);
      if (singletonObject == null) {
         if (this.singletonsCurrentlyInDestruction) {
            throw new BeanCreationNotAllowedException(beanName,
                  "Singleton bean creation not allowed while singletons of this factory are in destruction " +
                  "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
         }
         if (logger.isDebugEnabled()) {
            logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
         }
         beforeSingletonCreation(beanName);
         boolean newSingleton = false;
         boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
         if (recordSuppressedExceptions) {
            this.suppressedExceptions = new LinkedHashSet<>();
         }
         try {
            singletonObject = singletonFactory.getObject();
            newSingleton = true;
         }
         catch (IllegalStateException ex) {
            // Has the singleton object implicitly appeared in the meantime ->
            // if yes, proceed with it since the exception indicates that state.
            singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
               throw ex;
            }
         }
         catch (BeanCreationException ex) {
            if (recordSuppressedExceptions) {
               for (Exception suppressedException : this.suppressedExceptions) {
                  ex.addRelatedCause(suppressedException);
               }
            }
            throw ex;
         }
         finally {
            if (recordSuppressedExceptions) {
               this.suppressedExceptions = null;
            }
            afterSingletonCreation(beanName);
         }
         if (newSingleton) {
            addSingleton(beanName, singletonObject);
         }
      }
      return singletonObject;
   }
}

此时{

一级缓存:{A的beanName:BeanA} {B的beanName:BeanB}

二级缓存:null

三级缓存:null

})

总结:

【第一个doGetBean最初的getSingleton方法用来调用getEarlyBeanReference获取保存二级缓存数据】,【addSingletonFactory负责把数据存到三级缓存】,

【第二个doGetBean的getSingleton方法用来创建Bean,再addSingleton】,

【addSingleton方法是把成品Bean挪到一级缓存】,

【getEarlyBeanReference用来获取二级缓存对象引用】。

总结一句就是,半成品a的初始化创建了b的成品之后a再变成成品。

再发出一个提问:三级缓存有必要么?是不是二级缓存就够了?

谈一下对三级缓存和代理对象的理解,正常代理是在初始化之后的BeanPostProcessor中处理的,但是循环依赖时必须要给对方一个代理对象而不是初始对象,那就需要代理动作放在初始化时进行,也就是发生循环依赖走新逻辑,我理解这是为了保留原逻辑而不是全部推翻重写直接将代理过程挪到初始化中,那怎么判断发生了循环依赖呢,就在于getSingleton方法,如果一个BeanName进入了两次这个方法(正在创建中)那么就表示发生了循环依赖,此时调用匿名类的方法getEarlyBeanReference,如果有代理那么先创建代理对象并且把它放到二级缓存中,也就是三级缓存里放的时不可用对象,二级缓存中放的是可引用对象,一级缓存中放的是最终完成对象。如果流程改为发生循环依赖直接创建代理那么便不需要三级缓存了,直接使用二级缓存足以(此时二级缓存存放一般半成品和代理后的半成品)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值