Spring原始碼之容器的功能擴充套件和refresh方法解析

神祕傑克發表於2022-06-17

容器的功能擴充套件和refresh方法解析

在之前文章中我們瞭解了關於Spring中bean的載入流程,並一直使用BeanFactory介面以及它的預設實現類XmlBeanFactory,在Spring中還提供了另一個介面ApplicationContext,用於擴充套件BeanFactory中現有的功能。

首先BeanFactory和ApplicationContext都是用於載入bean的,但是相比之下,ApplicationContext提供了更多的擴充套件功能,ApplicationContext包含了BeanFactory的所有功能。通常我們會優先使用ApplicationContext。

我們來看看ApplicationContext多了哪些功能?

首先看一下寫法上的不同。

使用BeanFactory方式載入XML

final BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("spring-config.xml"));

使用ApplicationContext方式載入XML

final ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-config.xml");

我們開始點開ClassPathXmlApplicationContext的建構函式,進行分析。

public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
   this(new String[] {configLocation}, true, null);
}
public ClassPathXmlApplicationContext(
      String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
      throws BeansException {

   super(parent);
   setConfigLocations(configLocations);
   if (refresh) {
      refresh();
   }
}

在ClassPathXmlApplicationContext中可以將配置檔案路徑以陣列的形式傳入,對解析及功能實現都在refresh()方法中實現。

設定配置路徑

public void setConfigLocations(@Nullable String... locations) {
   if (locations != null) {
      Assert.noNullElements(locations, "Config locations must not be null");
      this.configLocations = new String[locations.length];
      for (int i = 0; i < locations.length; i++) {
         this.configLocations[i] = resolvePath(locations[i]).trim();
      }
   }
   else {
      this.configLocations = null;
   }
}

此函式主要解析給定的路徑陣列,如果陣列中包含特殊符號,如${var},那麼在resolvePath方法中會搜尋匹配的系統變數並替換。

擴充套件功能

設定完路徑後,就可以對檔案進行解析和各種功能的實現,可以說在refresh方法中幾乎包含了ApplicationContext中提供的全部功能,而且此函式的邏輯也十分清晰,可以很容易分析對應層次和邏輯。

public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
      // 準備重新整理的上下文環境,包括設定啟動時間,是否啟用標識位
      // 初始化屬性源(property source)配置
      prepareRefresh();

      // 初始化BeanFactory 並進行xml檔案讀取
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      // 對BeanFactory進行各種功能填充
      prepareBeanFactory(beanFactory);

      try {
         // 子類覆蓋方法做額外的處理
         postProcessBeanFactory(beanFactory);

         // 啟用各種BeanFactory處理器
         invokeBeanFactoryPostProcessors(beanFactory);

         // 註冊攔截bean建立的bean處理器,只是註冊,具體呼叫在getBean中
         registerBeanPostProcessors(beanFactory);

         // 為上下文初始化Message源,國際化處理
         initMessageSource();

         // 初始化應用訊息廣播器,並放入applicationEventMulticaster bean中
         initApplicationEventMulticaster();

         // 留給子類來初始化其他的bean
         onRefresh();

         // 在所有註冊的bean中查詢Listener bean,註冊到訊息廣播器中
         registerListeners();

         // 初始化剩下的單例bean (非惰性)
         finishBeanFactoryInitialization(beanFactory);

         //完成重新整理過程,通知生命週期處理器LifecycleProcessor重新整理過程,同時發出ContextRefreshEvent通知別人
         finishRefresh();
      }

      catch (BeansException ex) {
         if (logger.isWarnEnabled()) {
            logger.warn("Exception encountered during context initialization - " +
                  "cancelling refresh attempt: " + ex);
         }

         // 銷燬已經初始化的 singleton 的 Beans,以免有些 bean 會一直佔用資源
         destroyBeans();

         // 重置活動標誌
         cancelRefresh(ex);

         throw ex;
      }

      finally {
         //重置公共快取
         resetCommonCaches();
      }
   }
}

我們總結一下初始化的步驟。

  1. 初始化前的準備工作,例如對系統屬性或者環境變數進行準備及驗證
  2. 初始化BeanFactory,並對XML檔案進行讀取。之前我們說過ClassPathXmlApplicationContext中包含著BeanFactory所提供的一切特徵,那麼在這一步將會複用BeanFactory中的配置檔案讀取解析及其他功能,在這一步之後ClassPathXmlApplicationContext就已經包含了BeanFactory所提供的功能,也就是可以對bean進行提取等操作
  3. 對BeanFactory進行各種功能填充
  4. 子類覆蓋方法做額外的處理。主要用於我們在業務上做進一步擴充套件
  5. 啟用各種BeanFactory處理器
  6. 註冊攔截bean建立的bena處理器,這裡僅僅是註冊,真正呼叫在getBean中
  7. 為上下文初始化Message源,對不同語言的訊息體進行國際化處理
  8. 初始化應用訊息廣播器,並放入"applicationEventMulticaster" bean中
  9. 留給子類來初始化其他的bean
  10. 在所有註冊的bean中查詢listener bean,註冊到訊息廣播器中
  11. 初始化剩下的單例項(非惰性)
  12. 完成重新整理過程,通知生命週期處理器lifecycleProcessor重新整理過程,同時發出ContextRefreshEvent來通知別人

環境準備

prepareRefresh方法主要做些準備工作,比如對系統屬性及環境變數的初始化及驗證。

image-20220610155700599

  1. initPropertySources

該方法裡面是一個空實現,主要用於給我們根據需要去重寫該方法,並在方法中進行個性化的屬性處理及設定。

protected void initPropertySources() {
        // For subclasses: do nothing by default.
}
  1. validateRequiredProperties 該方法主要對屬性進行驗證。預設情況下什麼也沒校驗。在我們繼承了ClassPathXmlApplicationContext類重寫了initPropertySources方法後會進行相關校驗。

載入BeanFactory

obtainFreshBeanFactory 方法主要用來獲取BeanFactory,剛才說過ApplicationContext擁有BeanFactory的所有功能,這個方法就是實現BeanFactory的地方,也就是說呼叫完該方法後,applicationContext就擁有了BeanFactory的功能。

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
   //初始化BeanFactory,並進行XML檔案讀取,將得到的BeanFactory記錄到當前實體屬性中
   refreshBeanFactory();
   //返回當前實體的beanFactory屬性
   return getBeanFactory();
}
protected final void refreshBeanFactory() throws BeansException {
   if (hasBeanFactory()) {
      destroyBeans();
      closeBeanFactory();
   }
   try {
      DefaultListableBeanFactory beanFactory = createBeanFactory();
      beanFactory.setSerializationId(getId());
      customizeBeanFactory(beanFactory);
      loadBeanDefinitions(beanFactory);
      synchronized (this.beanFactoryMonitor) {
         this.beanFactory = beanFactory;
      }
   }
   catch (IOException ex) {
      throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
   }
}

我們進入AbstractRefreshableApplicationContext#refreshBeanFactory()方法中。

protected final void refreshBeanFactory() throws BeansException {
        //判斷是否存在beanFactory
        if (hasBeanFactory()) {
            //銷燬所有單例
            destroyBeans();
            //重置beanFactory
            closeBeanFactory();
        }
        try {
            //建立beanFactory
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            //設定序列化id
            beanFactory.setSerializationId(getId());
            //定製beanFactory,設定相關屬性,包括是否允許覆蓋同名稱不同定義的物件以及迴圈依賴
            customizeBeanFactory(beanFactory);
            //初始化DocumentReader,進行XML讀取和解析
            loadBeanDefinitions(beanFactory);
            synchronized (this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        }
        catch (IOException ex) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
        }
}

總結一下這個方法的流程:

  1. 建立DefaultListableBeanFactory。宣告方式為:BeanFactory bf = new XmlBeanFactory("beanFactoryTest.xml"),其中的XmlBeanFactory繼承自DefaultListableBeanFactory,並提供了XmlBeanDefinitionReader型別的reader屬性,也就是說DefaultListableBeanFactory是容器的基礎,必須首先例項化,這裡就是例項化DefaultListableBeanFactory的步驟
  2. 指定序列化ID
  3. 定製BeanFactory
  4. 載入BeanDefinition
  5. 使用全域性變數記錄BeanFactory類例項

定製BeanFactory

首先我們先了解customizeBeanFactory方法,該方法是在基本容器的基礎上,增加了是否允許覆蓋、是否允許擴充套件的設定。

protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
   //如果不為空,設定beanFactory物件響應的屬性,含義:是否允許覆蓋同名稱的不同定義的物件
   if (this.allowBeanDefinitionOverriding != null) {
      beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
   }
   //如果屬性不為空,設定給beanFactory物件相應屬性,含義:是否允許bean之間存在迴圈依賴
   if (this.allowCircularReferences != null) {
      beanFactory.setAllowCircularReferences(this.allowCircularReferences);
   }
}

具體這裡只是做了簡單的判斷,具體設定屬性的地方,使用子類覆蓋即可。例如:

/**
 * @author 神祕傑克
 * 公眾號: Java菜鳥程式設計師
 * @date 2022/6/12
 * @Description 自定義ClassPathXmlApplicationContext
 */
public class MyClassPathXmlApplicationContext extends ClassPathXmlApplicationContext {

   @Override
   protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
      super.setAllowBeanDefinitionOverriding(false);
      super.setAllowCircularReferences(false);
      super.customizeBeanFactory(beanFactory);
   }
}

載入BeanDefinition

在初始化了DefaultListableBeanFactory後,我們還需要XmlBeanDefinitionReader來讀取XML檔案,這個步驟中首先要做的就是初始化XmlBeanDefinitionReader。

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
   //為指定beanFactory建立XmlBeanDefinitionReader
   XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

   //進行環境變數的設定
   beanDefinitionReader.setEnvironment(this.getEnvironment());
   beanDefinitionReader.setResourceLoader(this);
   beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

   //對beanDefinitionReader進行設定,可以覆蓋
   initBeanDefinitionReader(beanDefinitionReader);
   loadBeanDefinitions(beanDefinitionReader);
}

初始化了DefaultListableBeanFactory和XmlBeanDefinitionReader後,我們就可以進行配置檔案的讀取了。最終XmlBeanDefinitionReader所去讀的BeanDefinitionHolder都會註冊到DefaultListableBeanFactory中。

經過該方法後型別為DefaultListableBeanFactory中的變數beanFactory已經包含了所有解析好的配置。關於配置檔案的讀取這一部分之前文章已經講過,這裡就不再贅述。

功能擴充套件

我們在完成了配置檔案解析後,我們接著進入prepareBeanFactory方法。

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
   //設定beanFactory的ClassLoader為當前context的ClassLoader
   beanFactory.setBeanClassLoader(getClassLoader());
   //設定beanFactory的表示式語言處理
   beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
   //為beanFactory增加了一個預設的propertyEditor,主要是對bean的屬性等設定管理的一個工具
   beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

   //新增BeanPostProcessor
   beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
   //設定幾個忽略自動裝配的介面
   beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
   beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
   beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
   beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
   beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
   beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

   //設定了幾個自動裝配的特殊規則
   beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
   beanFactory.registerResolvableDependency(ResourceLoader.class, this);
   beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
   beanFactory.registerResolvableDependency(ApplicationContext.class, this);

   //增加了ApplicationListenerDetector主要是檢測bean是否實現了ApplicationListener介面
   beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

   //增加對AspectJ的支援
   if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
      beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
      // Set a temporary ClassLoader for type matching.
      beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
   }

   //新增預設的系統環境bean
   if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
      beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
   }
   if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
      beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
   }
   if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
      beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
   }
}

該方法主要做了幾個方面的擴充套件:

  • 增加了對SpEL語言的支援
  • 增加了對屬性編輯器的支援
  • 增加了一些內建類,比如EnvironmentAware、MessageSourceAware的資訊注入
  • 設定了依賴功能可忽略的介面
  • 註冊了一些固定依賴的屬性
  • 增加AspectJ的支援
  • 將相關環境變數及屬性註冊以單例模式註冊

BeanFactory的後處理

BeanFactory作為Spring中容器的基礎,用於存放所有已經載入的bean,為了保證程式的高擴充套件性,Spring針對BeanFactory做了大量的擴充套件,比如PostProcessor等都是在這裡實現的。

啟用註冊的BeanFactoryPostProcessor

在學習之前,我們先了解一下BeanFactoryPostProcessor的用法。BeanFactoryPostProcessor介面和BeanPostProcessor類似,可以對bean的定義進行處理。也就是說,Spring IOC容器允許BeanFactoryPostProcessor在容器例項化任何bean之前讀取配置後設資料,並可以修改它。BeanFactoryPostProcessor可以配置多個,通過實現Ordered介面設定“order”來控制執行順序。

需要注意的是如果在容器中定義一個BeanFactoryPostProcessor,它僅僅對此容器中的bean進行後置處理。BeanFactoryPostProcessor不會對其他容器中的bean進行後置處理。

1.BeanFactoryPostProcessor的典型應用:PropertySourcesPlaceholderConfigurer

首先我們來看一下配置檔案:

<bean id="hello" class="cn.jack.Hello">
   <property name="msg">
      <value>${bean.msg}</value>
   </property>
</bean>

在裡面我們使用到了變數引用:${bean.msg},這就是Spring的分散配置,我們可以在配置檔案中配置該屬性的值。

application.properties

bean.msg=hi

然後我們再進行配置檔案的配置。

<bean id="helloHandler" class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>application.properties</value>
            </list>
        </property>
    </bean>

這時候就明白了,我們通過PreferencesPlaceholderConfigurer中進行獲取我們的配置資訊。我們檢視該類可以知道間接性繼承了BeanFactoryPostProcessor介面。

當Spring載入任何實現了這個介面的bean時,都會在bean工廠載入所有bena的配置之後執行postProcessBeanFactory方法。在方法中先後呼叫了mergeProperties、convertProperties、processProperties這三個方法,分別得到配置、將得到的配置進行轉換為合適的型別、最後將配置內容告知BeanFactory。

正是通過實現BeanFactoryPostProcessor,BeanFactory會在例項化任何bean之前獲得配置資訊,從而能夠正確解析bean配置檔案中的變數引用

PropertySourcesPlaceholderConfigurer已經取代了PropertyPlaceholderConfigurer,因為匯聚了Environment、多個PropertySource。所以它能夠控制取值優先順序、順序,並且還提供了訪問的方法,後期再想獲取也不是問題。

2.使用自定義BeanFactoryPostProcessor

我們自己實現一個自定義BeanFactoryPostProcessor,去除我們不想要顯示的屬性值的功能來展示自定義BeanFactoryPostProcessor的建立及使用,例如bean定義中我們遮蔽掉‘guapi’、‘shazi’。

<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 class="cn.jack.ObscenityRemovingBeanFactoryPostProcessor" id="customBeanFactoryPostProcessor">
        <property name="obscenities">
            <set>
                <value>guapi</value>
                <value>shazi</value>
            </set>
        </property>
    </bean>

    <bean class="cn.jack.SimpleBean" id="simpleBean">
        <property name="userName" value="jack"/>
        <property name="address" value="guapi"/>
        <property name="email" value="shazi"/>
    </bean>

</beans>
public class SimpleBean {

   private String userName;
   private String email;
   private String address;
        //getter  setter
}
public class ObscenityRemovingBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

   private final Set<String> obscenities;

   public ObscenityRemovingBeanFactoryPostProcessor() {
      this.obscenities = new HashSet<>();
   }

   /**
    * 將所有bean 的引數中含有 obscenities 集合中的值進行遮蔽
    */
   @Override
   public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
      String[] beanNames = beanFactory.getBeanDefinitionNames();
      for (String beanName : beanNames) {
         final BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
         StringValueResolver valueResolver = strVal -> {
            if (isObscene(strVal)){
               return  "*****";
            }
            return strVal;
         };
         final BeanDefinitionVisitor beanDefinitionVisitor = new BeanDefinitionVisitor(valueResolver);
         beanDefinitionVisitor.visitBeanDefinition(beanDefinition);
      }
   }

   public boolean isObscene(Object value){
      String potentialObscenity = value.toString().toUpperCase();
      return this.obscenities.contains(potentialObscenity);
   }

   public void setObscenities(Set<String> obscenities){
      this.obscenities.clear();
      for (String obscenity : obscenities) {
         this.obscenities.add(obscenity.toUpperCase());
      }
   }

}

啟動類:

public class Test {

   public static void main(String[] args) {
      ApplicationContext ac = new ClassPathXmlApplicationContext("beanFactory.xml");
      SimpleBean simpleBean = (SimpleBean) ac.getBean("simpleBean");
      System.out.println(simpleBean);
   }
}

輸出結果:

SimpleBean{userName='jack', email='*****', address='*****'}

我們通過ObscenityRemovingBeanFactoryPostProcessor我們很好的遮蔽掉了我們不想要顯示的屬性。

啟用BeanFactoryPostProcessor

我們在瞭解了BeanFactoryPostProcessor的用法之後就可以繼續回到我們的refresh方法中繼續研究原始碼了。

進入invokeBeanFactoryPostProcessors方法中。

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
   PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

   // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
   // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
   if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
      beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
      beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
   }
}

我們繼續進入具體過載方法中invokeBeanFactoryPostProcessors。

public static void invokeBeanFactoryPostProcessors(
      ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

   // 將已經執行過的BeanFactoryPostProcessor儲存在processedBeans,防止重複執行
   Set<String> processedBeans = new HashSet<>();
   //對BeanDefinitionRegistry型別進行處理
   if (beanFactory instanceof BeanDefinitionRegistry) {
      BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
      // 用來存放BeanFactoryPostProcessor物件
      List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
      // 用來存放BeanDefinitionRegistryPostProcessor物件
      // 方便統一執行實現了BeanDefinitionRegistryPostProcessor介面父類的方法
      List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
      // 處理外部定義的BeanFactoryPostProcessor,將BeanDefinitionRegistryPostProcessor與BeanFactoryPostProcessor區分開
      for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
         if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
            BeanDefinitionRegistryPostProcessor registryProcessor =
                  (BeanDefinitionRegistryPostProcessor) postProcessor;
            //對於BeanDefinitionRegistryPostProcessor型別,需要先呼叫此方法,再新增到集合中
            registryProcessor.postProcessBeanDefinitionRegistry(registry);
            registryProcessors.add(registryProcessor);
         } else {
            //記錄常規BeanFactoryPostProcessor
            regularPostProcessors.add(postProcessor);
         }
      }

      //存放當前需要執行的BeanDefinitionRegistryPostProcessor
      List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

      // 呼叫實現 PriorityOrdered 的 BeanDefinitionRegistryPostProcessor。
      // 獲取所有實現了BeanDefinitionRegistryPostProcessor介面的類名
      String[] postProcessorNames =
            beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
      for (String ppName : postProcessorNames) {
         //判斷當前類是否實現了PriorityOrdered介面
         if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            //將BeanDefinitionRegistryPostProcessor型別存入currentRegistryProcessors中
            currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
            // 提前存放到processedBeans,避免重複執行,但是此處還未執行
            processedBeans.add(ppName);
         }
      }
      //對currentRegistryProcessors集合中的BeanDefinitionRegistryPostProcessor型別進行排序
      sortPostProcessors(currentRegistryProcessors, beanFactory);
      // 新增到registryProcessors集合,用於後續執行父介面的postProcessBeanFactory方法
      registryProcessors.addAll(currentRegistryProcessors);
      // 遍歷集合,執行BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry()方法
      invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
      //執行完畢後清空該集合
      currentRegistryProcessors.clear();

      // 接著,呼叫實現 Ordered 的 BeanDefinitionRegistryPostProcessors
      // 這裡再次獲取BeanDefinitionRegistryPostProcessor,是因為有可能在上面方法執行過程中新增了BeanDefinitionRegistryPostProcessor
      // 而下面處理BeanFactoryPostProcessor的時候又不需要重複獲取了是為什麼呢?
      // 因為新增BeanFactoryPostProcessor與BeanDefinitionRegistryPostProcessor只能在BeanDefinitionRegistryPostProcessor中新增,在BeanFactoryPostProcessor是無法新增的
      for (String ppName : postProcessorNames) {
         // 判斷當前bean沒有被執行過,並且實現了Ordered介面
         if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
            //如果BeanFactory中沒有該Bean則會去建立該Bean
            currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
            processedBeans.add(ppName);
         }
      }
      sortPostProcessors(currentRegistryProcessors, beanFactory);
      registryProcessors.addAll(currentRegistryProcessors);
      invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
      currentRegistryProcessors.clear();

      //最後處理沒有實現Ordered與PriorityOrdered介面的BeanDefinitionRegistryPostProcessor
      boolean reiterate = true;
      while (reiterate) {
         reiterate = false;
         // 再次獲取BeanDefinitionRegistryPostProcessor
         postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
         for (String ppName : postProcessorNames) {
            if (!processedBeans.contains(ppName)) {
               // 將本次要執行的BeanDefinitionRegistryPostProcessor存放到currentRegistryProcessors
               currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
               processedBeans.add(ppName);
               reiterate = true;
            }
         }
         sortPostProcessors(currentRegistryProcessors, beanFactory);
         registryProcessors.addAll(currentRegistryProcessors);
         invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
         currentRegistryProcessors.clear();
      }

      //現在,呼叫到目前為止處理的所有處理器的 postProcessBeanFactory 回撥。
      invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
      invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
   } else {
      // BeanFactory如果不歸屬於BeanDefinitionRegistry型別,則直接執行beanFactoryPostProcessor
      invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
   }

   String[] postProcessorNames =
         beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

   // 用於存放實現了priorityOrdered介面的BeanFactoryPostProcessor
   List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
   // 用於存放實現了ordered介面的BeanFactoryPostProcessor名稱
   List<String> orderedPostProcessorNames = new ArrayList<>();
   // 用於存放無排序的BeanFactoryPostProcessor名稱
   List<String> nonOrderedPostProcessorNames = new ArrayList<>();
   for (String ppName : postProcessorNames) {
      // 如果已經執行過了,則不做處理
      if (processedBeans.contains(ppName)) {
         // skip - already processed in first phase above
      }
      // 如果實現了PriorityOrdered 則新增
      else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
         priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
      }
      // 如果實現了Ordered 則新增
      else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
         orderedPostProcessorNames.add(ppName);
      }
      //如果沒有排序則新增到指定集合
      else {
         nonOrderedPostProcessorNames.add(ppName);
      }
   }

   // 首先呼叫實現 PriorityOrdered 的 BeanFactoryPostProcessor。
   sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
   invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

   // 然後呼叫實現 Ordered 的 BeanFactoryPostProcessors。
   List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
   for (String postProcessorName : orderedPostProcessorNames) {
      orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
   }
   sortPostProcessors(orderedPostProcessors, beanFactory);
   invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

   // 最後呼叫其他沒有排序的 BeanFactoryPostProcessor。
   List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
   for (String postProcessorName : nonOrderedPostProcessorNames) {
      nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
   }
   invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

   // 清空快取
   beanFactory.clearMetadataCache();
}

註冊BeanPostProcessor

瞭解了BeanFactoryPostProcessors的呼叫後,我們現在來了解下BeanPostProcessor,這裡僅僅是註冊,並不是呼叫。真正的呼叫在bean例項化階段進行的。

在BeanFactory中並沒有實現後處理器的自動註冊功能,所以在呼叫的時候如果沒有進行主動註冊則是不能夠使用的。但是在ApplicationContext中新增了主動註冊功能。

比如自定義這樣的後處理器:

public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

   @Override
   public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
      System.out.println("===");
      return null;
   }
}
<bean class="cn.jack.MyInstantiationAwareBeanPostProcessor"/>

在使用ApplicationContext方式獲取bean的時候會在獲取之前列印出“===”,在BeanFactory方式進行bean的載入是不會有該列印的。

這個特性就是在registerBeanPostProcessors中實現的。

public static void registerBeanPostProcessors(
      ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
   //獲取所有實現BeanPostProcessor介面的類
   String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

   //註冊一個 BeanPostProcessorChecker,用來記錄 bean 在 BeanPostProcessor 例項化時的資訊
   int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
   beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

   //區分實現不同介面的 BeanPostProcessors
   List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
   List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
   List<String> orderedPostProcessorNames = new ArrayList<>();
   List<String> nonOrderedPostProcessorNames = new ArrayList<>();
   //根據不同型別進行add
   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);
      }
   }

   // 排序後執行註冊實現了 PriorityOrdered 的 BeanPostProcessors
   sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
   registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

   //註冊實現Ordered介面的BeanPostProcessors
   List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
   for (String ppName : orderedPostProcessorNames) {
      //拿到ppName對應的BeanPostProcessor例項物件
      BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
      //將ppName對應的BeanPostProcessor例項物件新增到orderedPostProcessors, 準備執行註冊
      orderedPostProcessors.add(pp);
      if (pp instanceof MergedBeanDefinitionPostProcessor) {
         //如果ppName對應的bean例項也實現了MergedBeanDefinitionPostProcessor介面,則新增到該集合中
         internalPostProcessors.add(pp);
      }
   }
   //對orderedPostProcessors進行排序並註冊
   sortPostProcessors(orderedPostProcessors, beanFactory);
   registerBeanPostProcessors(beanFactory, orderedPostProcessors);

   //註冊所有常規的BeanPostProcessors,過程同上
   List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
   for (String ppName : nonOrderedPostProcessorNames) {
      BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
      nonOrderedPostProcessors.add(pp);
      if (pp instanceof MergedBeanDefinitionPostProcessor) {
         internalPostProcessors.add(pp);
      }
   }
   registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

   //註冊所有mergedBeanDefinitionPostProcessor型別的BeanPostProcessor,並非重複註冊
   //在beanFactory.addBeanPostProcessor中會先移除已經存在的BeanPostProcessor
   sortPostProcessors(internalPostProcessors, beanFactory);
   registerBeanPostProcessors(beanFactory, internalPostProcessors);

   // 新增ApplicationListener探測器
   beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

初始化訊息資源

在initMessageSource中主要功能是提取配置檔案中的messageSource,並將其記錄在Spring容器中,也就是ApplicationContext中。如果使用者未設定資原始檔的話,則獲取Spring預設的配置delegatingMessageSource。

protected void initMessageSource() {
   ConfigurableListableBeanFactory beanFactory = getBeanFactory();
   // Bean 的名稱必須要是 messageSource
   if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) { //MESSAGE_SOURCE_BEAN_NAME = messageSource
      this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
      // Make MessageSource aware of parent MessageSource.
      if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
         HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
         if (hms.getParentMessageSource() == null) {
            // Only set parent context as parent MessageSource if no parent MessageSource
            // registered already.
            hms.setParentMessageSource(getInternalParentMessageSource());
         }
      }
      if (logger.isTraceEnabled()) {
         logger.trace("Using MessageSource [" + this.messageSource + "]");
      }
   }
   else {
      //如果使用者並沒有定義配置檔案,那麼使用臨時的DelegatingMessageSource以便於作為呼叫getMessage的返回
      DelegatingMessageSource dms = new DelegatingMessageSource();
      dms.setParentMessageSource(getInternalParentMessageSource());
      this.messageSource = dms;
      beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
      if (logger.isTraceEnabled()) {
         logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
      }
   }
}

這裡規定資原始檔必須為messageSource,否則就會獲取不到自定義資源配置。

初始化ApplicationEventMulticaster

initApplicationEventMulticaster方法實現比較簡單,存在兩種情況:

  • 如果使用者自定義了事件廣播器,那麼就是用使用者自定義的事件廣播器
  • 如果使用者沒有自定義事件廣播器,那麼使用預設的ApplicationEventMulticaster
protected void initApplicationEventMulticaster() {
   ConfigurableListableBeanFactory beanFactory = getBeanFactory();
   //判斷容器中是否存在BeanDefinitionName為applicationEventMulticaster的bd,也就是自定義的事件監聽多路廣播器,必須實現ApplicationEventMulticaster介面
   if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
      this.applicationEventMulticaster =
            beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
      if (logger.isTraceEnabled()) {
         logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
      }
   }
   else {
      //如果沒有,則預設採用SimpleApplicationEventMulticaster
      this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
      beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
      if (logger.isTraceEnabled()) {
         logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
               "[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
      }
   }
}

最後,作為廣播器,一定是用於存放監聽器並在合適的時候呼叫監聽器,我們進入預設的廣播器實現類SimpleApplicationEventMulticaster中看一下。

看到如下方法:

public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
   ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
   Executor executor = getTaskExecutor();
   for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
      if (executor != null) {
         executor.execute(() -> invokeListener(listener, event));
      }
      else {
         invokeListener(listener, event);
      }
   }
}

可以推斷,當產生Spring事件的時候會預設使用SimpleApplicationEventMulticaster的multicastEvent來廣播事件,遍歷所有監聽器,並使用監聽器中的onApplicationEvent方法來進行監聽器的處理。而對於每個監聽器來說其實都可以獲取到產生的事件,但是是否進行處理則由事件監聽器決定。

註冊監聽器

我們反覆提到了監聽器,我們接下來看一下Spring註冊監聽器的時候又做了哪些邏輯操作?

protected void registerListeners() {
   // 首先註冊靜態的指定的監聽器,註冊的是特殊的事件監聽器,而不是配置中的bean
   for (ApplicationListener<?> listener : getApplicationListeners()) {
      getApplicationEventMulticaster().addApplicationListener(listener);
   }

   // 這裡不會初始化FactoryBean,我們需要保留所有的普通bean
   // 不會例項化這些bean,讓後置處理器可以感知到它們
   String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
   for (String listenerBeanName : listenerBeanNames) {
      getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
   }

   // 現在有了事件廣播組,釋出之前的應用事件
   Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
   this.earlyApplicationEvents = null;
   if (earlyEventsToProcess != null) {
      for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
         getApplicationEventMulticaster().multicastEvent(earlyEvent);
      }
   }
}

只是將一些特殊的監聽器註冊到廣播組中,那些在bean配置檔案中實現了ApplicationListener介面的類還沒有例項化,所以此時只是將name儲存到了廣播組中,將這些監聽器註冊到廣播組中的操作時在bean的後置處理器中完成的,那時候bean的例項化已經完成了。

初始化非延遲載入單例

完成BeanFactory的初始化工作,其中包括ConversionService的設定、配置凍結以及非延遲載入的bean的初始化工作。

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
   // 初始化此上下文的轉換服務
   if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
         beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
      beanFactory.setConversionService(
            beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
   }

   // 如果beanFactory之前沒有註冊解析器,則註冊預設的解析器,例如${}解析成真正的屬性:主要用於註解屬性值的解析
   if (!beanFactory.hasEmbeddedValueResolver()) {
      beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
   }

   //處理 @EnableLoadTimeWeaving 或  <context:load-time-weaver/> 標記的類
   String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
   for (String weaverAwareName : weaverAwareNames) {
      getBean(weaverAwareName);
   }

   //臨時類載入器設定為空
   beanFactory.setTempClassLoader(null);

   //凍結所有的bean定義,說明註冊的bean定義將不被修改或者進一步處理
   beanFactory.freezeConfiguration();

   //初始化剩下的單例例項(非惰性)
   beanFactory.preInstantiateSingletons();
}

首先,我們先了解下ConversionService類所提供的作用。

1.ConversionService的設定

之前我們提到可以用自定義型別轉換器把String型別轉換為Date,在Spring中也提供了使用Converter來進行轉換。

2.凍結配置

凍結所有的bean定義,說明註冊的bean定義將不被修改或者進行任何一步的處理。

public void freezeConfiguration() {
   this.configurationFrozen = true;
   this.frozenBeanDefinitionNames = StringUtils.toStringArray(this.beanDefinitionNames);
}

3.初始化延遲載入

ApplicationContext實現的預設行為就是在啟動時將所有單例bean提前進行例項化。提前例項化也就意味著作為初始化過程的一部分,ApplicationContext例項會建立並配置所有單例bean,這個例項化過程就是在finishBeanFactoryInitialization方法中的preInstantiateSingletons方法中完成的。

public void preInstantiateSingletons() throws BeansException {
   if (logger.isTraceEnabled()) {
      logger.trace("Pre-instantiating singletons in " + this);
   }

   //建立beanDefinitionNames的副本beanNames用於後續的遍歷,以允許init等方法註冊新的bean定義
   List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

   //遍歷beanNames,觸發所有非懶載入單例bean的初始化
   for (String beanName : beanNames) {
      //獲取beanName對應的MergedBeanDefinition
      RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
      //bd對應的不是抽象類 && 並且是單例 && 並且不是懶載入
      if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
         //判斷是否為FactoryBean
         if (isFactoryBean(beanName)) {
            //通過字首&和beanName拿到Bean
            Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
            //如果為FactoryBean
            if (bean instanceof FactoryBean) {
               final FactoryBean<?> factory = (FactoryBean<?>) bean;
               //判斷這個FactoryBean是否希望急切的初始化
               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());
               }
               //如果希望急切的初始化,則通過beanName獲取bean例項
               if (isEagerInit) {
                  getBean(beanName);
               }
            }
         }
         else {
            //如果beanName對應的bean不是FactoryBean,只是普通Bean,通過beanName獲取bean例項
            getBean(beanName);
         }
      }
   }

   //遍歷beanNames,觸發所有SmartInitializingSingleton的後初始化回撥
   for (String beanName : beanNames) {
      //拿到beanName對應的bean例項
      Object singletonInstance = getSingleton(beanName);
      //判斷singletonInstance是否實現了SmartInitializingSingleton介面
      if (singletonInstance instanceof SmartInitializingSingleton) {
         final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
         //觸發SmartInitializingSingleton實現類的afterSingletonsInstantiated方法
         if (System.getSecurityManager() != null) {
            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
               smartSingleton.afterSingletonsInstantiated();
               return null;
            }, getAccessControlContext());
         }
         else {
            smartSingleton.afterSingletonsInstantiated();
         }
      }
   }
}

finishRefresh

在Spring中提供了Lifecycle介面,該介面包含start/stop方法,實現此介面後Spring會保證在啟動時候呼叫其start方法開始宣告週期,並在Spring關閉時候呼叫stop方法來結束宣告週期。通常用來配置後臺程式,在啟動後一直執行(比如MQ)而ApplicationContext最後一步finishRefresh方法就是實現這一功能。

protected void finishRefresh() {
   //清除資源快取
   clearResourceCaches();

   //1.為此上下文初始化生命週期處理器
   initLifecycleProcessor();

   //2.首先將重新整理完畢事件傳播到生命週期處理器(觸發isAutoStartup方法返回true的SmartLifecycle的start方法)
   getLifecycleProcessor().onRefresh();

   //3.推送上下文重新整理完畢事件到相應的監聽器
   publishEvent(new ContextRefreshedEvent(this));

   // Participate in LiveBeansView MBean, if active.
   LiveBeansView.registerApplicationContext(this);
}

1.initLifecycleProcessor

當ApplicationContext啟動或停止時,它會通過LifecycleProcessor來和所有宣告的bean的週期做狀態更新,而在LifecycleProcessor的使用前首先進行初始化。

protected void initLifecycleProcessor() {
   ConfigurableListableBeanFactory beanFactory = getBeanFactory();
   //判斷BeanFactory是否已經存在生命週期處理器(beanName=lifecycleProcessor)
   if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
      this.lifecycleProcessor =
            beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
      if (logger.isTraceEnabled()) {
         logger.trace("Using LifecycleProcessor [" + this.lifecycleProcessor + "]");
      }
   }
   else {
      //如果不存在,則使用DefaultLifecycleProcessor
      DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
      defaultProcessor.setBeanFactory(beanFactory);
      this.lifecycleProcessor = defaultProcessor;
      // 並將DefaultLifecycleProcessor作為預設的生命週期處理器,註冊到BeanFactory中
      beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
      if (logger.isTraceEnabled()) {
         logger.trace("No '" + LIFECYCLE_PROCESSOR_BEAN_NAME + "' bean, using " +
               "[" + this.lifecycleProcessor.getClass().getSimpleName() + "]");
      }
   }
}

2.onRefresh

啟動所有實現了Lifecycle介面的bean

public void onRefresh() {
   startBeans(true);
   this.running = true;
}
private void startBeans(boolean autoStartupOnly) {
   Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
   Map<Integer, LifecycleGroup> phases = new HashMap<>();
   lifecycleBeans.forEach((beanName, bean) -> {
      if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
         int phase = getPhase(bean);
         LifecycleGroup group = phases.get(phase);
         if (group == null) {
            group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);
            phases.put(phase, group);
         }
         group.add(beanName, bean);
      }
   });
   if (!phases.isEmpty()) {
      List<Integer> keys = new ArrayList<>(phases.keySet());
      Collections.sort(keys);
      for (Integer key : keys) {
         phases.get(key).start();
      }
   }
}

3.publishEvent

當完成ApplicationContext初始化的時候,要通過Spring中的釋出機制來發出ContextRefreshedEvent事件,以保證對應的監聽器可以做進一步的邏輯處理。

protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
   Assert.notNull(event, "Event must not be null");

   //如有必要,將事件裝飾為ApplicationEvent
   ApplicationEvent applicationEvent;
   if (event instanceof ApplicationEvent) {
      applicationEvent = (ApplicationEvent) event;
   }
   else {
      applicationEvent = new PayloadApplicationEvent<>(this, event);
      if (eventType == null) {
         eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
      }
   }

   // Multicast right now if possible - or lazily once the multicaster is initialized
   if (this.earlyApplicationEvents != null) {
      this.earlyApplicationEvents.add(applicationEvent);
   }
   else {
      //使用事件廣播器廣播事件到相應的監聽器
      getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
   }

   //通過parent釋出事件
   if (this.parent != null) {
      if (this.parent instanceof AbstractApplicationContext) {
         ((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
      }
      else {
         this.parent.publishEvent(event);
      }
   }
}

到這裡,refresh方法就解析完成了。下一步就是AOP了。

相關文章