天天看點

Spring架構系列之構造方法BeanDefinition掃描原理02

作者:85後程式猿

上一篇我們将AnnotationConfigApplicationContext構造函數的整體流程梳理一遍,今天我們來詳細聊聊Spring是如何掃描得到所有需要被管理的Bean資訊的,這裡用一個專業名詞來表示Bean資訊叫BeanDefinition,後面我們都簡稱BD,我們後面會有專門章節來說明BD的類繼承關系。

上一篇我們講到invokeBeanFactoryPostProcessors是完成掃描的核心方法,那麼我們進入該方法來看看:

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
   PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
   if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
      beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
      beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
   }
}           

關鍵代碼就是PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()),在進一入invokeBeanFactoryPostProcessors方法:

public static void invokeBeanFactoryPostProcessors(
      ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
   Set<String> processedBeans = new HashSet<>();

   if (beanFactory instanceof BeanDefinitionRegistry) {
      BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
      List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
      List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

      // 關鍵點一、這個beanFactoryPostProcessors集合一般情況下都是空的,除非我們手動調用容器的addBeanFactoryPostProcessor方法
      for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
         if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
            BeanDefinitionRegistryPostProcessor registryProcessor =
                  (BeanDefinitionRegistryPostProcessor) postProcessor;
            registryProcessor.postProcessBeanDefinitionRegistry(registry);
            registryProcessors.add(registryProcessor);
         }else {
            regularPostProcessors.add(postProcessor);
         }
      } 
      List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
      //關鍵點二、執行BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法
      String[] postProcessorNames =
            beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
      for (String ppName : postProcessorNames) {
         if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
            processedBeans.add(ppName);
         }
      }
      sortPostProcessors(currentRegistryProcessors, beanFactory);
      registryProcessors.addAll(currentRegistryProcessors);
      invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
      currentRegistryProcessors.clear();

      postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
      for (String ppName : postProcessorNames) {
         if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
            currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
            processedBeans.add(ppName);
         }
      }
      sortPostProcessors(currentRegistryProcessors, beanFactory);
      registryProcessors.addAll(currentRegistryProcessors);
      invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
      currentRegistryProcessors.clear();
			
     boolean reiterate = true;
      while (reiterate) {
         reiterate = false;
         postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
         for (String ppName : postProcessorNames) {
            if (!processedBeans.contains(ppName)) {
               currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
               processedBeans.add(ppName);
               reiterate = true;
            }
         }
         sortPostProcessors(currentRegistryProcessors, beanFactory);
         registryProcessors.addAll(currentRegistryProcessors);
         invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
         currentRegistryProcessors.clear();
      }
      invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
			invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
   }else { 
      invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
   } 
  
  //關鍵點三
   String[] postProcessorNames =beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
   List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
   List<String> orderedPostProcessorNames = new ArrayList<>();
   List<String> nonOrderedPostProcessorNames = new ArrayList<>();
   for (String ppName : postProcessorNames) {
      if (processedBeans.contains(ppName)) {
         // skip - already processed in first phase above
      }else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
         priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
      }else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
         orderedPostProcessorNames.add(ppName);
      }else {
         nonOrderedPostProcessorNames.add(ppName);
      }
   }

   //關鍵點四、執行BeanFactoryPostProcessor的postProcessBeanFactory方法
   sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
   invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

   List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
   for (String postProcessorName : orderedPostProcessorNames) {
      orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
   }
   sortPostProcessors(orderedPostProcessors, beanFactory);
   invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
  
   List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
   for (String postProcessorName : nonOrderedPostProcessorNames) {
      nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
   }
   invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
  
   beanFactory.clearMetadataCache();
}           

代碼有點多,但是歸納起來就做了兩件事:第一執行BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法,也就是對BeanDefinition進行處理;第二執行BeanFactoryPostProcessor的postProcessBeanFactory方法,執行BeanFactory的後置處理器邏輯。下面我們就來詳細說說。

  • 關鍵點一
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
   if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
      BeanDefinitionRegistryPostProcessor registryProcessor =
            (BeanDefinitionRegistryPostProcessor) postProcessor;
      registryProcessor.postProcessBeanDefinitionRegistry(registry);
      registryProcessors.add(registryProcessor);
   }else {
      regularPostProcessors.add(postProcessor);
   }
}           

beanFactoryPostProcessors一般情況下都是空的,除非我們手動調用容器的addBeanFactoryPostProcessor方法,這裡Spring提供了一個擴充點,一般情況下不會使用。

  • 關鍵點二
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
String[] postProcessorNames =
         beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
   for (String ppName : postProcessorNames) {
      // 
      if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
         currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
         processedBeans.add(ppName);
      }
   }           

首先:

看currentRegistryProcessors這個對象,他的主要作用就是記錄目前将要執行的BeanDefinitionRegistryPostProcessor執行個體,首先擷取到所有的BeanDefinitionRegistryPostProcessor,然後将PriorityOrdered類型的BeanDefinitionRegistryPostProcessor對象添加到currentRegistryProcessors集合中。注意這裡擷取到的BeanDefinitionRegistryPostProcessor類型對象隻有一個ConfigurationClassPostProcessor,那這個類是什麼時候添加到BeanFactory裡面去的呢?咱們還記得上一篇構造函數裡面建立了一個reader對象嗎?代碼如下:

this.reader = new AnnotatedBeanDefinitionReader(this);           

AnnotatedBeanDefinitionReader的構造函數中調用了如下代碼:

AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);           

這段代碼中建立了五個類型的對象,并将這五個類型對象添加到了BeanFactory中:

1.ConfigurationClassPostProcessor
2.AutowiredAnnotationBeanPostProcessor
3.CommonAnnotationBeanPostProcessor
4.EventListenerMethodProcessor
5.DefaultEventListenerFactory           

而ConfigurationClassPostProcessor又實作了BeanDefinitionRegistryPostProcessor和PriorityOrdered:

public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
      PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {...}           

然後執行如下代碼:

invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);           

這裡開始執行上述的ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法,這個方法就是掃描得到所有的BeanDefinition,由于這裡比較複雜,後續我們專門文章來分析,這裡先跳過,大家隻要知道它的作用即可。

其次:

依次類推,将執行Ordered.class類型的BeanDefinitionRegistryPostProcessor執行個體對象。

最後

需要執行普通的BeanDefinitionRegistryPostProcessor執行個體對象:

boolean reiterate = true;
while (reiterate) {
   reiterate = false;
   postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
   for (String ppName : postProcessorNames) {
      if (!processedBeans.contains(ppName)) {
         currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
         processedBeans.add(ppName);
         reiterate = true;
      }
   }
   sortPostProcessors(currentRegistryProcessors, beanFactory);
   registryProcessors.addAll(currentRegistryProcessors);
   invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
   currentRegistryProcessors.clear();
}           

但是很奇怪,這裡為啥要加個while循環?Spring有病吧?當然沒病,人家Spring考慮的周全。這裡表示執行上面沒有執行的BeanDefinitionRegistryPostProcessor,而且你在執行過程中,可能會産生新的BeanDefinitionRegistryPostProcessor對象,是以才用個while循環,直到執行完所有的BeanDefinitionRegistryPostProcessor才結束;

執行完後,再執行BeanDefinitionRegistryPostProcessor實作類的postProcessBeanFactory方法(因為BeanDefinitionRegistryPostProcessor也是BeanFactoryPostProcessor的實作),這裡就會執行ConfigurationClassPostProcessor的postProcessBeanFactory方法:

invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);           

ConfigurationClassPostProcessor的postProcessBeanFactory方法有點特别:

public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
   int factoryId = System.identityHashCode(beanFactory);
   if (this.factoriesPostProcessed.contains(factoryId)) {
      throw new IllegalStateException(
            "postProcessBeanFactory already called on this post-processor against " + beanFactory);
   }
   this.factoriesPostProcessed.add(factoryId);
   if (!this.registriesPostProcessed.contains(factoryId)) {
      processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
   }
   enhanceConfigurationClasses(beanFactory);
   beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}           

enhanceConfigurationClasses這個方法用于判斷是否需要對配置類生成代理對象?什麼是配置類?增加了@Configuration注解的類是配置了,它有什麼特點呢?凡是在配置類中被@Bean聲明的對象都需要代理,是以這裡需要對@Configuration類型的對象進行特殊處理;

然後添加ImportAwareBeanPostProcessor後置處理器,這個是對@import注解進行處理的Bean的後置處理器,後續我們再講。

  • 關鍵點三
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
   if (processedBeans.contains(ppName)) {
      // skip - already processed in first phase above
   }else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
      priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
   }else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
      orderedPostProcessorNames.add(ppName);
   }else {
      nonOrderedPostProcessorNames.add(ppName);
   }
}           

這裡看代碼很簡單,就是把所有的BeanFactoryPostProcessor對象分别放到三個集合裡面去,然後按優先級先後執行priorityOrderedPostProcessors、orderedPostProcessorNames、nonOrderedPostProcessorNames中的BeanFactoryPostProcessor對象,但是為什麼不像上面的BeanDefinitionRegistryPostProcessor一樣處理,而是直接分到三個集合裡面呢?這個也很簡單,因為執行BeanFactoryPostProcessor方法不會産生新的BeanFactoryPostProcessor對象,是以為了提升效率,直接分組到不同的集合即可。

  • 關鍵點四

這裡就開始執行BeanFactoryPostProcessor的postProcessBeanFactory方法了,先執行priorityOrderedPostProcessors集合中的,其次執行orderedPostProcessorNames集合中的,最後執行nonOrderedPostProcessorNames集合中的。

Spring架構系列之構造方法BeanDefinition掃描原理02