天天看點

Spring BeanFacoty doCreateBean方法分析

上一篇,我們分析到了doCreateBean,現在繼續:

先看看時序圖

Spring BeanFacoty doCreateBean方法分析
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
    // Instantiate the bean.
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
      instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    if (instanceWrapper == null) {
      //*************************5.4.1  
      instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
    Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);






    // Allow post-processors to modify the merged bean definition.
    //*************************5.4.2  
    synchronized (mbd.postProcessingLock) {
      if (!mbd.postProcessed) {
        applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
        mbd.postProcessed = true;
      }
    }


    // Eagerly cache singletons to be able to resolve circular references
    // even when triggered by lifecycle interfaces like BeanFactoryAware.
    //*************************5.4.3 處理循環依賴的問題
    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() {
        public Object getObject() throws BeansException {
          return getEarlyBeanReference(beanName, mbd, bean);
        }
      });
    }


    // Initialize the bean instance.
    Object exposedObject = bean;
    try {
      //*************************5.4.4 将mdb中的值放到instanceWrapper中
      populateBean(beanName, mbd, instanceWrapper);
      if (exposedObject != null) {
        //*************************5.4.5 正兒八經的初始化
        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);
      }
    }


    //似乎還是循環依賴的問題
    if (earlySingletonExposure) {
      Object earlySingletonReference = getSingleton(beanName, false);
      if (earlySingletonReference != null) {
        if (exposedObject == bean) {
          exposedObject = earlySingletonReference;
        }
        else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
          String[] dependentBeans = getDependentBeans(beanName);
          Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
          for (String dependentBean : dependentBeans) {
            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 " +
                "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
          }
        }
      }
    }


    // Register bean as disposable.
    try {
      //*************************5.4.6 注冊銷毀方法
      registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    catch (BeanDefinitionValidationException ex) {
      throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }


    return exposedObject;
  }      

在5.4.1處

首先判斷是否有factory-method屬性

即:

<bean id="bar" class="...StaticBarInterfaceFactory" factory-method="getInstance"/>      

如果有就直接通過工廠方法生産之。 參見 拙作spring中工廠方法 javascript:void(0)

如果沒有有預設的構造方法,且bean中包含constructor-arg

<bean id="newsBean3" class="com.luhy.spring.hello.FXNewsBean" scope="singleton"> 
  <constructor-arg>      
    <value>This is a configurable message</value>       
  </constructor-arg>   
</bean>      

就調用預設的含參構造方法。

否則調用instantiateBean

AbstractAutowireCapableBeanFactory.java
  protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
    try {
      Object beanInstance;
      final BeanFactory parent = this;
      if (System.getSecurityManager() != null) {
        beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
          public Object run() {
            return getInstantiationStrategy().instantiate(mbd, beanName, parent);
          }
        }, getAccessControlContext());
      }
      else {
        beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
      }
      BeanWrapper bw = new BeanWrapperImpl(beanInstance);
      initBeanWrapper(bw);
      return bw;
    }
    catch (Throwable ex) {
      throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
    }
  }      

我們在AbstractAutowireCapableBeanFactory裡可以看到

/** Strategy for creating bean instances */
private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();
getInstantiationStrategy()傳回的是InstantiationStrategy接口的實作類,預設是CglibSubclassingInstantiationStrategy。      

通過cglib生成執行個體對象。

至5.4.1,BeanWrapper的生成基本清晰了。

5.4.2處是允許其他修改beanDefinition,這主要是允許其他元件提供xml不能提供的資訊。如使用Annotation增強Bean定義等。這通過類ergedBeanDefinitionPostProcessor來完成,如果容器中提供了此類實作,則會調用進行bean增強。如CommonAnnotationBeanPostProcessor類,會在bean定義中追加如 @Resource之類的bean property引用資訊。此代碼如下所示:

protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class beanType, String beanName)
      throws BeansException {


    try {
      for (BeanPostProcessor bp : getBeanPostProcessors()) {
        if (bp instanceof MergedBeanDefinitionPostProcessor) {
          MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
          bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
        }
      }
    }
    catch (Exception ex) {
      throw new BeanCreationException(mbd.getResourceDescription(), beanName,
          "Post-processing failed of bean type [" + beanType + "] failed", ex);
    }
  }      

在5.4.3處,關于循環依賴問題,可以參考

​​ http://www.iflym.com/index.php/code/201208280001.html​​

在5.4.4處populateBean(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw)

說實話,我第一回看到這方法的時候,populate,流行的?流行的bean? 呵呵,見笑了。

在populate裡面

/**
   * Populate the bean instance in the given BeanWrapper with the property values
   * from the bean definition.
   * @param beanName the name of the bean
   * @param mbd the bean definition for the bean
   * @param bw BeanWrapper with bean instance
   */
  protected void populateBean(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw) {
    PropertyValues pvs = mbd.getPropertyValues();


    if (bw == null) {
      if (!pvs.isEmpty()) {
        throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
      }
      else {
        // Skip property population phase for null instance.
        return;
      }
    }


    // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
    // state of the bean before properties are set. This can be used, for example,
    // to support styles of field injection.
    //*******************5.4.4.1
    boolean continueWithPropertyPopulation = true;


    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
      for (BeanPostProcessor bp : getBeanPostProcessors()) {
        if (bp instanceof InstantiationAwareBeanPostProcessor) {
          InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
          if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
            continueWithPropertyPopulation = false;
            break;
          }
        }
      }
    }


    if (!continueWithPropertyPopulation) {
      return;
    }


    //*******************5.4.4.2
    if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
        mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
      MutablePropertyValues newPvs = new MutablePropertyValues(pvs);


      // Add property values based on autowire by name if applicable.
      if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
        autowireByName(beanName, mbd, bw, newPvs);
      }


      // Add property values based on autowire by type if applicable.
      if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
        autowireByType(beanName, mbd, bw, newPvs);
      }


      pvs = newPvs;
    }


    boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
    boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);




    //*******************5.4.4.3
    if (hasInstAwareBpps || needsDepCheck) {
      PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw);
      if (hasInstAwareBpps) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
          if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
            if (pvs == null) {
              return;
            }
          }
        }
      }
      if (needsDepCheck) {
        checkDependencies(beanName, mbd, filteredPds, pvs);
      }
    }
    //*******************5.4.4.4
    applyPropertyValues(beanName, mbd, bw, pvs);
  }      

好長呀,慢慢來,這裡大概可以分為4部分

首先5.4.4.1

如果所要擷取的bean實作了InstantiationAwareBeanPostProcessor接口,就調用其postProcessAfterInstantiation方法。

<span >    </span>// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
    // state of the bean before properties are set. This can be used, for example,
    // to support styles of field injection.
    boolean continueWithPropertyPopulation = true;


    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
      for (BeanPostProcessor bp : getBeanPostProcessors()) {
        if (bp instanceof InstantiationAwareBeanPostProcessor) {
          InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
          if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
            continueWithPropertyPopulation = false;
            break;
          }
        }
      }
    }


    if (!continueWithPropertyPopulation) {
      return;
    }      

多說幾句,postProcessAfterInstantiation的傳回值是一個boolean,如果傳回值是false,就說明已經屬性處理已經結束了。後面的代碼就不運作了。

接着5.4.4.2

if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
        mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
      MutablePropertyValues newPvs = new MutablePropertyValues(pvs);


      // Add property values based on autowire by name if applicable.
      if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
        autowireByName(beanName, mbd, bw, newPvs);
      }


      // Add property values based on autowire by type if applicable.
      if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
        autowireByType(beanName, mbd, bw, newPvs);
      }


      pvs = newPvs;
    }      

不需要解釋了吧,就是處理autowire标簽。

再然後5.4.4.3

給InstantiationAwareBeanPostProcessor機會以處理屬性資訊,比如在xml中描述了Annotation定義,使用了<context:annotation-config/>,那麼就會使用類CommonAnnotationBeanPostProcessor進行注解類屬性注入。如下代碼所示:

if (hasInstAwareBpps || needsDepCheck) {
      PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw);
      if (hasInstAwareBpps) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
          if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
            if (pvs == null) {
              return;
            }
          }
        }
      }
      if (needsDepCheck) {
        checkDependencies(beanName, mbd, filteredPds, pvs);
      }
    }      

我們看下面的解釋:

Spring BeanFacoty doCreateBean方法分析

最後5.4.4.4

applyPropertyValues(beanName, mbd, bw, pvs)幹的事情就是填充值。

這裡都幹了什麼事情,我舉個例子。

<bean id="newsBean2" class="com.luhy.spring.hello.FXNewsBean" scope="prototype"> 
      <property name="p"> 
     <value>dlf</value> 
      </property> 
</bean>      

com.luhy.spring.hello.FXNewsBean中p這個屬性是一個Person。

如何将字元串"dlf"(在xml中,所有的資訊不都是字元麼)轉換為person呢?

我們需要下面這個類:

public class PersonEditor extends PropertyEditorSupport {
  @Override
  public void setAsText(String text) throws IllegalArgumentException {
    Person p = new Person();
    p.setName(text);
    System.out.println("setAsTest");
    setValue(p);
  }
}      

那麼什麼時候調用這個PersonEditor呢?就在5.4.5.4的applyPropertyValues裡。

當然,這裡我隻是舉個例子。這裡還包括集合類型的轉換,基本類型的轉換等等。

關于5.4.5

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
    if (System.getSecurityManager() != null) {
      AccessController.doPrivileged(new PrivilegedAction<Object>() {
        public Object run() {
          invokeAwareMethods(beanName, bean);
          return null;
        }
      }, getAccessControlContext());
    }
    else {
      //處理XXAware接口的實作
                        //beanFactoryAware這這個處理
      invokeAwareMethods(beanName, bean);
    }
    
    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
      //處理postProcessBeforeInitialization
<span >      </span>//在這裡處理ApplicationContextAware(使用ApplicationContextAwareProcessor)
      wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }


    try {
      //這裡面調用了 InitializingBean的afterPropertiesSet
      //同時還有init-method指定的方法
      invokeInitMethods(beanName, wrappedBean, mbd);
    }
    catch (Throwable ex) {
      throw new BeanCreationException(
          (mbd != null ? mbd.getResourceDescription() : null),
          beanName, "Invocation of init method failed", ex);
    }


    if (mbd == null || !mbd.isSynthetic()) {
      //postProcessAfterInitialization方法
      wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }
    return wrappedBean;
  }      

總結一下初始化順序

XXAware接口的實作->postProcessBeforeInitialization->InitializingBean的afterPropertiesSet-> custom Init方法->postProcessAfterInitialization

  OK.這就是bean初始化的順序啦!

5.4.6注冊銷毀方法

至此,擷取對象完畢。

參考資料

​​http://www.iflym.com/index.php/code/201208280001.html​​ 循環引用

​​http://www.iflym.com/index.php/code/201208290001.html​​ Spring中擷取一個bean的流程-1