Spring如何解决循环依赖问题

wuchangjian2021-11-15 13:07:19编程学习

首先是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再变成成品。

相关文章

ajax实现图片的回显功能

前端页面 给文件上传域绑定一个改变事件 <tr> <td c...

Ubuntu18.04.4 安装XRDP远程桌面终极、最简方案

Ubuntu18.04.4 安装XRDP远程桌面终极、最简方案_weixin_43315...

重量转换之克、两、斤

售卖方式、按份或者按重,商品单位转换 @Data public...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。