Spring源碼閱讀之registerBeanPostProcessors()源碼分析

上篇文章我們分析了invokeBeanFactoryPostProcessors()方法的實現,主要是BeanFactoryBeanDefinition定義在實例化之前做一些前置操作。接下來本文來看看registerBeanPostProcessors()的實現,上篇文章留了一個疑問,大家是否還記得?我們在本篇文章揭曉答案,本篇先來解讀源碼,後面附上測試用例。

  1. 回到AbstractApplicationContext.refresh()方法的registerBeanPostProcessors()地方,我們來看看實現,從方法中可以看出,調用了PostProcessorRegistrationDelegate類的靜態方法。

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
	PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}

  1. PostProcessorRegistrationDelegate.registerBeanPostProcessors方法用於註冊所有BeanPostProcessor實例(該方法比較長,但是流程很清晰,耐心開完)。看源碼前首先需要明白兩個類:

  • BeanPostProcessor: 一切BeanPostProcessor實例都需要直接或間接該接口。

  • MergedBeanDefinitionPostProcessor: 是一個接口,實現了BeanPostProcessor接口,並給出了一個方法。所以實現了該接口的類比實現了BeanPostProcessor類的優先級更高,功能更豐富。

public static void registerBeanPostProcessors(
			ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
      // Step1:獲取所有直接或間接實現了BeanPostProcessor接口的BeanDefinition對應的processor名字。內部實現見源碼分析3
      String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

      // Register BeanPostProcessorChecker that logs an info message when
      // a bean is created during BeanPostProcessor instantiation, i.e. when
      // a bean is not eligible for getting processed by all BeanPostProcessors.
      int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
      // Step2:添加一個BeanPostProcessor檢查器,該檢查器的作用:是在創建BeanPostProcessor時記錄日誌、創建BeanPostProcessor發生異常時記錄日誌等等操作。
      beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

      // Separate between BeanPostProcessors that implement PriorityOrdered,
      // Ordered, and the rest.
      // Step3:存放實現了PriorityOrdered接口的BeanPostProcessor,其優先級最高。
      // PriorityOrdered接口作用:用於對BeanPostProcessor進行優先級排序的。和上一篇關於BeanFactoryPostProcessor的排序功能一樣。
      List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
      // Step4:存放內部實現的BeanPostProcessor。
      List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
      // Step5:存放實現了Ordered接口的BeanPostProcessor,其優先級低於PriorityOrdered接口
      // Ordered接口作用:也是排序功能。
      List<String> orderedPostProcessorNames = new ArrayList<>();
      // Step6:存放除去內部的和有優先級的BeanPostProcessor後,剩餘的BeanPostProcessor
      List<String> nonOrderedPostProcessorNames = new ArrayList<>();
      // Step7:遍歷BeanPostProcessor對應的名字,進行分堆和創建Bean實例操作。關於創建Bean實例在後面創建Bean實例專門介紹,這裏不展開。
      for (String ppName : postProcessorNames) {
          if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
              BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
              priorityOrderedPostProcessors.add(pp);
              if (pp instanceof MergedBeanDefinitionPostProcessor) {
                  internalPostProcessors.add(pp);
              }
          }
          else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
              orderedPostProcessorNames.add(ppName);
          }
          else {
              nonOrderedPostProcessorNames.add(ppName);
          }
      }

      // First, register the BeanPostProcessors that implement PriorityOrdered.
      // Step8:對PriorityOrdered相關的BeanPostProcessor進行排序操作,排序的依據是重寫了PriorityOrdered的getOrder的返回值
      sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
      // Step9:將排序後的BeanPostProcessor一次註冊到BeanFactory裏面。
      registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

      // Next, register the BeanPostProcessors that implement Ordered.
      // Step10:遍歷實現了Ordered接口的BeanPostProcessor,如果改processor實現了MergedBeanDefinitionPostProcessor接口,將其加入到內部的BeanPostProcessor集合裏面。
      List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
      for (String ppName : orderedPostProcessorNames) {
          BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
          orderedPostProcessors.add(pp);
          if (pp instanceof MergedBeanDefinitionPostProcessor) {
              internalPostProcessors.add(pp);
          }
      }
      // Step11:排序
      sortPostProcessors(orderedPostProcessors, beanFactory);
      // Step12:註冊
      registerBeanPostProcessors(beanFactory, orderedPostProcessors);

      // Now, register all regular BeanPostProcessors.
      // Step13:對無優先級的BeanPostProcessor進行遍歷,將實現了MergedBeanDefinitionPostProcessor接口的加入到內部BeanPostProcessor的集合中
      List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
      for (String ppName : nonOrderedPostProcessorNames) {
          BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
          nonOrderedPostProcessors.add(pp);
          if (pp instanceof MergedBeanDefinitionPostProcessor) {
              internalPostProcessors.add(pp);
          }
      }
      // Step14:沒有先後順序,一次註冊這些Bean實例到BeanFactory裏面。
      registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

      // Finally, re-register all internal BeanPostProcessors.
      // Step15:最後對所有的內部BeanPostProcessor實例進行排序操作,並將其註冊到BeanFactory裏面。
      sortPostProcessors(internalPostProcessors, beanFactory);
      registerBeanPostProcessors(beanFactory, internalPostProcessors);

      // Re-register post-processor for detecting inner beans as ApplicationListeners,
      // moving it to the end of the processor chain (for picking up proxies etc).
      // Step16:對BeanFactory添加一個一個全局的監聽器
      beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
	}

  1. 我們來看下BeanPostProcessor對應的beanName是怎麼獲取到的。

public String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
      // Step1:當前BeanFactory是否凍結,凍結返回true(就是說當前BeanFactory的BeanDefinition定義是否不可以被修改)
      if (!isConfigurationFrozen() || type == null || !allowEagerInit) {
          return doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit);
      }
      // Step2:從當前BeanFactory的緩存裏面獲取對應的BeanPostProcessor名字。如果有直接返回(在Spring源碼中大量用到了這種緩存機制來提升Spring容器初始化的速度)
      Map<Class<?>, String[]> cache =
              (includeNonSingletons ? this.allBeanNamesByType : this.singletonBeanNamesByType);
      String[] resolvedBeanNames = cache.get(type);
      if (resolvedBeanNames != null) {
          return resolvedBeanNames;
      }
      // Step3:都沒有取到,則根據type去加載相應的名字
      resolvedBeanNames = doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, true);
      if (ClassUtils.isCacheSafe(type, getBeanClassLoader())) {
          cache.put(type, resolvedBeanNames);
      }
      return resolvedBeanNames;
}

  1. 來看看根據type如果獲取到對應的BeanPostProcessor名字,這裏稍微比較複雜一點,歸納一下其實就是遍歷所有的beanName,然後拿type去匹配,如果能匹配的上就認爲是目標的BeanPostProcessor對應的baneName

private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
      List<String> result = new ArrayList<>();

      // Check all bean definitions.
      // Step1:遍歷當前BeanFactory裏面所有的beanNames
      for (String beanName : this.beanDefinitionNames) {
          // Only consider bean as eligible if the bean name
          // is not defined as alias for some other bean.
          // Setp1.1:判斷當前beanName是否是別名,所以if裏面的邏輯是針對非別名的beanName處理。
          if (!isAlias(beanName)) {
              try {
                  // Step1.1.1:根據beanName獲取對應的BeanDefinition定義,具體邏輯之前介紹過,在這裏就不展開了。
                  RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                  // Only check bean definition if it is complete.
                  // Step1.1.2:檢查BeanDefinition定義是否完整。即當前BeanDefinition定義是:非抽象的 && (提前加載 || (有對應的BeanClass || 非懶加載 || 允許提前加載bean)&& 是否提前初始化指定類型的bean)
                  // 總結大概意思就是當前BeanDefinition定義是非抽象的且可以提前加載
                  if (!mbd.isAbstract() && (allowEagerInit ||
                          (mbd.hasBeanClass() || !mbd.isLazyInit() || isAllowEagerClassLoading()) &&
                                  !requiresEagerInitForType(mbd.getFactoryBeanName()))) {
                      // In case of FactoryBean, match object created by FactoryBean.
                      // Setp1.1.2.1:根據beanName和對應的BeanDefinition定義判斷是否是一個FactoryBean。
                      boolean isFactoryBean = isFactoryBean(beanName, mbd);
                      // Step1.1.2.2:返回此BeanDefinition被修飾的BeanDefinitionHolder對象。
                      BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
                      // Step1.1.2.3:判斷beanName和對應的BeanDefinition是否匹配
                      boolean matchFound =
                              (allowEagerInit || !isFactoryBean ||
                                      (dbd != null && !mbd.isLazyInit()) || containsSingleton(beanName)) &&
                              (includeNonSingletons ||
                                      (dbd != null ? mbd.isSingleton() : isSingleton(beanName))) &&
                              isTypeMatch(beanName, type);
                      // Step1.1.2.4:沒匹配到 %% 是BeanFactory,則添加BeanFactory的前綴,在匹配一次。
                      if (!matchFound && isFactoryBean) {
                          // In case of FactoryBean, try to match FactoryBean instance itself next.
                          beanName = FACTORY_BEAN_PREFIX + beanName;
                          matchFound = (includeNonSingletons || mbd.isSingleton()) && isTypeMatch(beanName, type);
                      }
                      // Step1.1.2.5:匹配到則將beanName加到結果集中
                      if (matchFound) {
                          result.add(beanName);
                      }
                  }
              }
              catch (CannotLoadBeanClassException ex) {
                  if (allowEagerInit) {
                      throw ex;
                  }
                  // Probably contains a placeholder: let's ignore it for type matching purposes.
                  if (this.logger.isDebugEnabled()) {
                      this.logger.debug("Ignoring bean class loading failure for bean '" + beanName + "'", ex);
                  }
                  onSuppressedException(ex);
              }
              catch (BeanDefinitionStoreException ex) {
                  if (allowEagerInit) {
                      throw ex;
                  }
                  // Probably contains a placeholder: let's ignore it for type matching purposes.
                  if (this.logger.isDebugEnabled()) {
                      this.logger.debug("Ignoring unresolvable metadata in bean definition '" + beanName + "'", ex);
                  }
                  onSuppressedException(ex);
              }
          }
      }

      // Check manually registered singletons too.
      // Step2:檢查手動註冊的單例Bean
      for (String beanName : this.manualSingletonNames) {
          try {
              // In case of FactoryBean, match object created by FactoryBean.
              // Step2.1:是一個FactoryBean並且匹配到了,則加入到結果集中
              if (isFactoryBean(beanName)) {
                  if ((includeNonSingletons || isSingleton(beanName)) && isTypeMatch(beanName, type)) {
                      result.add(beanName);
                      // Match found for this bean: do not match FactoryBean itself anymore.
                      continue;
                  }
                  // In case of FactoryBean, try to match FactoryBean itself next.
                  beanName = FACTORY_BEAN_PREFIX + beanName;
              }
              // Match raw bean instance (might be raw FactoryBean).
              // Step2.2:非FactoryBean並且匹配到了,則加入到結果集中
              if (isTypeMatch(beanName, type)) {
                  result.add(beanName);
              }
          }
          catch (NoSuchBeanDefinitionException ex) {
              // Shouldn't happen - probably a result of circular reference resolution...
              if (logger.isDebugEnabled()) {
                  logger.debug("Failed to check manually registered singleton with name '" + beanName + "'", ex);
              }
          }
      }
      // Step3:返回匹配到的結果集
      return StringUtils.toStringArray(result);
}

5. 以上即爲源碼的分析,所以的工作就是將BeanPostProcessor註冊到BeanFactory裏面,然後在 bean 實例初始化前做一些工作(關於這個我們在介紹 bean 實例初始化的地方會介紹)。接下來,來看一個例子來理解一下整個過程。

// 使用方法比較簡單,我們創建一個MyBeanPostProcessor,其實現了BeanPostProcessor接口和Ordered的接口
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.Ordered;

/**
 * @author zxz
 * 自定義BeanPostProcessor
 */
public class MyBeanPostProcessor implements BeanPostProcessor, Ordered {
    public int getOrder() {
        // 這個返回值是用來對實現了Ordered接口的BeanPostProcessor進行排序的
        return 0;
    }

    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("MyBeanPostProcessor.postProcessBeforeInitialization,該方法是在Bean實例初始化前被調用,執行一些特殊的邏輯");
        // 這裏寫自己要做的特殊邏輯
        if (bean instanceof UserService) {
            System.out.println("UserService instance bean before");
        }
        return bean;
    }

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("MyBeanPostProcessor.postProcessAfterInitialization,該方法實在Bean實例初始化後被調用,執行特殊的邏輯");
        // 這裏寫自己要做的特殊邏輯
        if (bean instanceof UserService) {
            System.out.println("UserService instance bean after");
        }
        return bean;
    }
}
// xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="userService" class="UserServiceImpl"/>
    <!-- 注入自定義的BeanPostProcessor -->
    <bean id="myBeanPostProcessor" class="MyBeanPostProcessor"/>
</beans>
// 單測
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class JuniteTest {

    @Test
    public void testBeanPostProcessor() {
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        UserService userService = context.getBean(UserService.class);
        userService.save();
    }
}

從輸出結果來看,首先調用了重寫的postProcessBeforeInitialization()postProcessAfterInitialization()方法。然後在UserServicesave方法。


6. 以上內容爲BeanPostProcessor註冊的全流程。現在來回答一下上篇文章留下的問題,invokeBeanFactoryPostProcessors()registerBeanPostProcessors()區別?

  • invokeBeanFactoryPostProcessors():操作的對象是BeanDefinition定義,在此階段我們隨意修改BeanDefinition定義的屬性相關。BeanFactoryPostProcessor只提供了一個方法:postProcessBeanFactory()

  • registerBeanPostProcessors():操作的對象是BeanDefinition定義對應的 Bean 實例,BeanPostProcessor提供了兩個方法:postProcessBeforeInitialization()postProcessAfterInitialization()


總結

registerBeanPostProcessors方法主要功能是將所有實現了BeanPostProcessor接口或者實現了MergedBeanDefinitionPostProcessor接口的類對應的實例註冊到BeanFactory中(注意是將 Bean 實例註冊到BeanFactory裏面)。

在該方法內部將BeanPostProcessor分爲四類,分別是實現了PriorityOrdered接口的、實現了Ordered接口的、內部的和普通的。按照優先級依次排序將這四類BeanPostProcessor註冊到BeanFactory裏面。

BeanPostProcessor提供的兩個方法的調用時機是在 Bean 實例初始化前後的時候被調用。

下一篇我們就來介紹 Spring 最核心的一個方法:finishBeanFactoryInitialization(),看看它是怎麼把BeanDefinition定義轉化成對應的 Bean 實例的,敬請期待。


歡迎關注我,共同學習

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章