spring5 源碼深度解析—–ApplicationContext容器refresh過程

  • 2019 年 10 月 3 日
  • 筆記

在之前的博文中我們一直以BeanFactory介面以及它的默認實現類XmlBeanFactory為例進行分析,但是Spring中還提供了另一個介面ApplicationContext,用於擴展BeanFactory中現有的功能。
ApplicationContext和BeanFactory兩者都是用於載入Bean的,但是相比之下,ApplicationContext提供了更多的擴展功能,簡而言之:ApplicationContext包含BeanFactory的所有功能。通常建議比優先使用ApplicationContext,除非在一些限制的場合,比如位元組長度對記憶體有很大的影響時(Applet),絕大多數“典型的”企業應用系統,ApplicationContext就是需要使用的。
那麼究竟ApplicationContext比BeanFactory多了哪些功能?首先我們來看看使用兩個不同的類去載入配置文件在寫法上的不同如下程式碼:

//使用BeanFactory方式載入XML.  BeanFactory bf = new XmlBeanFactory(new ClassPathResource("beanFactoryTest.xml"));    //使用ApplicationContext方式載入XML.  ApplicationContext bf = new ClassPathXmlApplicationContext("beanFactoryTest.xml");

接下來我們就以ClassPathXmlApplicationContext作為切入點,開始對整體功能進行分析。首先看下其構造函數:

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

設置路徑是必不可少的步驟,ClassPathXmlApplicationContext中可以將配置文件路徑以數組的方式傳入,ClassPathXmlApplicationContext可以對數組進行解析並進行載入。而對於解析及功能實現都在refresh()中實現。

設置配置路徑

在ClassPathXmlApplicationContext中支援多個配置文件以數組方式同時傳入,以下是設置配置路徑方法程式碼:

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) {          //準備刷新的上下文 環境            prepareRefresh();          //初始化BeanFactory,並進行XML文件讀取            /*           * ClassPathXMLApplicationContext包含著BeanFactory所提供的一切特徵,在這一步驟中將會復用           * BeanFactory中的配置文件讀取解析及其他功能,這一步之後,ClassPathXmlApplicationContext           * 實際上就已經包含了BeanFactory所提供的功能,也就是可以進行Bean的提取等基礎操作了。           */          ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();          //對beanFactory進行各種功能填充            prepareBeanFactory(beanFactory);          try {              //子類覆蓋方法做額外處理                /*               * Spring之所以強大,為世人所推崇,除了它功能上為大家提供了便利外,還有一方面是它的               * 完美架構,開放式的架構讓使用它的程式設計師很容易根據業務需要擴展已經存在的功能。這種開放式               * 的設計在Spring中隨處可見,例如在本例中就提供了一個空的函數實現postProcessBeanFactory來               * 方便程式猿在業務上做進一步擴展               */              postProcessBeanFactory(beanFactory);              //激活各種beanFactory處理器                invokeBeanFactoryPostProcessors(beanFactory);              //註冊攔截Bean創建的Bean處理器,這裡只是註冊,真正的調用實在getBean時候               registerBeanPostProcessors(beanFactory);              //為上下文初始化Message源,即不同語言的消息體,國際化處理                initMessageSource();              //初始化應用消息廣播器,並放入“applicationEventMulticaster”bean中                initApplicationEventMulticaster();              //留給子類來初始化其它的Bean                onRefresh();              //在所有註冊的bean中查找Listener bean,註冊到消息廣播器中                registerListeners();              //初始化剩下的單實例(非惰性的)                finishBeanFactoryInitialization(beanFactory);              //完成刷新過程,通知生命周期處理器lifecycleProcessor刷新過程,同時發出ContextRefreshEvent通知別人                finishRefresh();          }          catch (BeansException ex) {              if (logger.isWarnEnabled()) {                  logger.warn("Exception encountered during context initialization - " +                          "cancelling refresh attempt: " + ex);              }              destroyBeans();              cancelRefresh(ex);              throw ex;          }          finally {              resetCommonCaches();          }      }  }

我們簡單的分析下程式碼的步驟:
(1)初始化前的準備工作,例如對系統屬性或者環境變數進行準備及驗證。
在某種情況下項目的使用需要讀取某些系統變數,而這個變數的設置很可能會影響著系統的正確性,那麼ClassPathXmlApplicationContext為我們提供的這個準備函數就顯得非常必要,他可以在spring啟動的時候提前對必須的環境變數進行存在性驗證。
(2)初始化BeanFactory,並進行XML文件讀取。
之前提到ClassPathXmlApplicationContext包含著對BeanFactory所提供的一切特徵,那麼這一步中將會復用BeanFactory中的配置文件讀取解析其他功能,這一步之後ClassPathXmlApplicationContext實際上就已經包含了BeanFactory所提供的功能,也就是可以進行Bean的提取等基本操作了。
(3)對BeanFactory進行各種功能填充
@Qualifier和@Autowired應該是大家非常熟悉的註解了,那麼這兩個註解正是在這一步驟中增加支援的。
(4)子類覆蓋方法做額外處理。
spring之所以強大,為世人所推崇,除了它功能上為大家提供了遍歷外,還有一方面是它完美的架構,開放式的架構讓使用它的程式設計師很容易根據業務需要擴展已經存在的功能。這種開放式的設計在spring中隨處可見,例如本利中就提供了一個空的函數實現postProcessBeanFactory來方便程式設計師在業務上做進一步的擴展。
(5)激活各種BeanFactory處理器
(6)註冊攔截bean創建的bean處理器,這裡只是註冊,真正的調用是在getBean時候
(7)為上下文初始化Message源,及對不同語言的小西天進行國際化處理
(8)初始化應用消息廣播器,並放入“applicationEventMulticaster”bean中
(9)留給子類來初始化其他的bean
(10)在所有註冊的bean中查找listener bean,註冊到消息廣播器中
(11)初始化剩下的單實例(非惰性的)
(12)完成刷新過程,通知生命周期處理器lifecycleProcessor刷新過程,同時發出ContextRefreshEvent通知別人。
接下來我們就詳細的講解每一個過程

prepareRefresh刷新上下文的準備工作

/**   * 準備刷新上下文環境,設置它的啟動日期和活動標誌,以及執行任何屬性源的初始化。   * Prepare this context for refreshing, setting its startup date and   * active flag as well as performing any initialization of property sources.   */  protected void prepareRefresh() {      this.startupDate = System.currentTimeMillis();      this.closed.set(false);      this.active.set(true);        // 在上下文環境中初始化任何佔位符屬性源。(空的方法,留給子類覆蓋)      initPropertySources();        // 驗證需要的屬性文件是否都已放入環境中      getEnvironment().validateRequiredProperties();        // 允許收集早期的應用程式事件,一旦有了多播器,就可以發布……      this.earlyApplicationEvents = new LinkedHashSet<>();  }

obtainFreshBeanFactory->讀取xml並初始化BeanFactory

obtainFreshBeanFactory方法從字面理解是獲取beanFactory.ApplicationContext是對BeanFactory的擴展,在其基礎上添加了大量的基礎應用,obtainFreshBeanFactory正式實現beanFactory的地方,經過這個函數後ApplicationContext就有了BeanFactory的全部功能。我們看下此方法的程式碼:

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {      //初始化BeanFactory,並進行XML文件讀取,並將得到的BeanFactory記錄在當前實體的屬性中        refreshBeanFactory();      //返回當前實體的beanFactory屬性       ConfigurableListableBeanFactory beanFactory = getBeanFactory();      if (logger.isDebugEnabled()) {          logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);      }      return beanFactory;  }

繼續深入到refreshBeanFactory方法中,方法的實現是在AbstractRefreshableApplicationContext中:

@Override  protected final void refreshBeanFactory() throws BeansException {      if (hasBeanFactory()) {          destroyBeans();          closeBeanFactory();      }      try {          //創建DefaultListableBeanFactory            /*           * 以前我們分析BeanFactory的時候,不知道是否還有印象,聲明方式為:BeanFactory bf =           * new XmlBeanFactory("beanFactoryTest.xml"),其中的XmlBeanFactory繼承自DefaulltListableBeanFactory;           * 並提供了XmlBeanDefinitionReader類型的reader屬性,也就是說DefaultListableBeanFactory是容器的基礎。必須           * 首先要實例化。           */          DefaultListableBeanFactory beanFactory = createBeanFactory();          //為了序列化指定id,如果需要的話,讓這個BeanFactory從id反序列化到BeanFactory對象            beanFactory.setSerializationId(getId());          //訂製beanFactory,設置相關屬性,包括是否允許覆蓋同名稱的不同定義的對象以及循環依賴以及設置          //@Autowired和Qualifier註解解析器QualifierAnnotationAutowireCandidateResolver            customizeBeanFactory(beanFactory);          //載入BeanDefiniton            loadBeanDefinitions(beanFactory);          synchronized (this.beanFactoryMonitor) {              //使用全局變數記錄BeanFactory實例。              //因為DefaultListableBeanFactory類型的變數beanFactory是函數內部的局部變數,              //所以要使用全局變數記錄解析結果                this.beanFactory = beanFactory;          }      }      catch (IOException ex) {          throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);      }  }

載入BeanDefinition

在第一步中提到了將ClassPathXmlApplicationContext與XMLBeanFactory創建的對比,除了初始化DefaultListableBeanFactory外,還需要XmlBeanDefinitionReader來讀取XML,那麼在loadBeanDefinitions方法中首先要做的就是初始化XmlBeanDefinitonReader,我們跟著到loadBeanDefinitions(beanFactory)方法體中,我們看到的是在AbstractXmlApplicationContext中實現的,具體程式碼如下:

@Override  protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {      // Create a new XmlBeanDefinitionReader for the given BeanFactory.      XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);        // Configure the bean definition reader with this context's      // resource loading environment.      beanDefinitionReader.setEnvironment(this.getEnvironment());      beanDefinitionReader.setResourceLoader(this);      beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));        // Allow a subclass to provide custom initialization of the reader,      // then proceed with actually loading the bean definitions.      initBeanDefinitionReader(beanDefinitionReader);      loadBeanDefinitions(beanDefinitionReader);  }

在初始化了DefaultListableBeanFactory和XmlBeanDefinitionReader後,就可以進行配置文件的讀取了。繼續進入到loadBeanDefinitions(beanDefinitionReader)方法體中,程式碼如下:

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {      Resource[] configResources = getConfigResources();      if (configResources != null) {          reader.loadBeanDefinitions(configResources);      }      String[] configLocations = getConfigLocations();      if (configLocations != null) {          reader.loadBeanDefinitions(configLocations);      }  }

因為在XmlBeanDefinitionReader中已經將之前初始化的DefaultListableBeanFactory註冊進去了,所以XmlBeanDefinitionReader所讀取的BeanDefinitionHolder都會註冊到DefinitionListableBeanFactory中,也就是經過這個步驟,DefaultListableBeanFactory的變數beanFactory已經包含了所有解析好的配置。

功能擴展

如上圖所示prepareBeanFactory(beanFactory)就是在功能上擴展的方法,而在進入這個方法前spring已經完成了對配置的解析,接下來我們詳細分析下次函數,進入方法體:

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {      // Tell the internal bean factory to use the context's class loader etc.      //設置beanFactory的classLoader為當前context的classloader        beanFactory.setBeanClassLoader(getClassLoader());      //設置beanFactory的表達式語言處理器,Spring3增加了表達式語言的支援,      //默認可以使用#{bean.xxx}的形式來調用相關屬性值        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));      //為beanFactory增加了一個的propertyEditor,這個主要是對bean的屬性等設置管理的一個工具      beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));        // Configure the bean factory with context callbacks.      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 interface not registered as resolvable type in a plain factory.      // MessageSource registered (and found for autowiring) as a bean.      //設置了幾個自動裝配的特殊規則      beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);      beanFactory.registerResolvableDependency(ResourceLoader.class, this);      beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);      beanFactory.registerResolvableDependency(ApplicationContext.class, this);        // Register early post-processor for detecting inner beans as ApplicationListeners.      beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));        // Detect a LoadTimeWeaver and prepare for weaving, if found.      //增加對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()));      }        // Register default environment beans.      //添加默認的系統環境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());      }  }

詳細分析下程式碼發現上面函數主要是在以下方法進行了擴展:
(1)對SPEL語言的支援
(2)增加對屬性編輯器的支援
(3)增加對一些內置類的支援,如EnvironmentAware、MessageSourceAware的注入
(4)設置了依賴功能可忽略的介面
(5)註冊一些固定依賴的屬性
(6)增加了AspectJ的支援
(7)將相關環境變數及屬性以單例模式註冊 

增加對SPEL語言的支援

Spring表達式語言全稱為“Spring Expression Language”,縮寫為“SpEL”,類似於Struts 2x中使用的OGNL語言,SpEL是單獨模組,只依賴於core模組,不依賴於其他模組,可以單獨使用。
SpEL使用#{…}作為定界符,所有在大框號中的字元都將被認為是SpEL,使用格式如下:

<util:properties id="database" location="classpath:db.properties">  </util:properties>  <bean id="dbcp" class="org.apache.commons.dbcp.BasicDataSource">    <property name="username" value="#{database.user}"></property>    <property name="password" value="#{database.pwd}"></property>    <property name="driverClassName" value="#{database.driver}"></property>    <property name="url" value="#{database.url}"></property>  </bean>

上面只是列舉了其中最簡單的使用方式,SpEL功能非常強大,使用好可以大大提高開發效率。在源碼中通過程式碼beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver()),註冊語言解析器,就可以對SpEL進行解析了,那麼之後是在什麼地方調用這個解析器的呢?
之前說beanFactory中說過Spring在bean進行初始化的時候會有屬性填充的一步,而在這一步中Spring會調用AbstractAutowireCapabelBeanFactory類的applyPropertyValues來進行屬性值得解析。同時這個步驟中一般通過AbstractBeanFactory中的evaluateBeanDefinitionString方法進行SpEL解析,方法程式碼如下:

protected Object evaluateBeanDefinitionString(String value, BeanDefinition beanDefinition) {      if (this.beanExpressionResolver == null) {          return value;      }      Scope scope = (beanDefinition != null ? getRegisteredScope(beanDefinition.getScope()) : null);      return this.beanExpressionResolver.evaluate(value, new BeanExpressionContext(this, scope));  } 

BeanFactory的後處理

BeanFactory作為spring中容器功能的基礎,用於存放所有已經載入的bean,為例保證程式上的高可擴展性,spring針對BeanFactory做了大量的擴展,比如我們熟悉的PostProcessor就是在這裡實現的。接下來我們就深入分析下BeanFactory後處理

激活註冊的BeanFactoryPostProcessor

在正是介紹BeanFactoryPostProcessor的後處理前我們先簡單的了解下其用法,BeanFactoryPostProcessor介面跟BeanPostProcessor類似,都可以對bean的定義(配置元數據)進行處理,也就是說spring IoC容器允許BeanFactoryPostProcessor在容器實際實例化任何其他的bean之前讀取配置元數據,並可能修改他。也可以配置多個BeanFactoryPostProcessor,可以通過order屬性來控制BeanFactoryPostProcessor的執行順序(此屬性必須當BeanFactoryPostProcessor實現了Ordered的介面時才可以賒賬,因此在實現BeanFactoryPostProcessor時應該考慮實現Ordered介面)。
如果想改變世界的bean實例(例如從配置元數據創建的對象),那最好使用BeanPostProcessor。同樣的BeanFactoryPostProcessor的作用域範圍是容器級別的,它只是和你鎖使用的容器有關。如果你在容器中定義了一個BeanFactoryPostProcessor,它僅僅對此容器中的bean進行後置處理。BeanFactoryPostProcessor不會對定義在另一個容器中的bean進行後置處理,即使這兩個容器都在同一層次上。在spring中存在對於BeanFactoryPostProcessor的典型應用,如PropertyPlaceholderConfigurer。

BeanFactoryPostProcessor的典型應用:PropertyPlaceholderConfigurer

有時候我們在閱讀spring的配置文件中的Bean的描述時,會遇到類似如下情況:

<bean id="user" class="com.yhl.myspring.demo.applicationcontext.User">      <property name="name" value="${user.name}"/>      <property name="birthday" value="${user.birthday"/>  </bean>

這其中出現了變數:user.nameuser.name、{user.birthday},這是spring的分散配置,可以在另外的配置文件中為user.name、user.birthday指定值,例如在bean.properties文件中定義:

user.name = xiaoming  user.birthday = 2019-04-19

當訪問名為user的bean時,其name屬性就會被字元串xiaoming替換,那spring框架是怎麼知道存在這樣的配置文件呢,這個就是PropertyPlaceholderConfigurer,需要在配置文件中添加一下程式碼:

<bean id="userHandler" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">      <property name="locations">          <list>              <value>classpath:bean.properties</value>          </list>      </property>  </bean>

在這個bean中指定了配置文件的位置。其實還是有個問題,這個userHandler只不過是spring框架管理的一個bean,並沒有被別的bean或者對象引用,spring的beanFactory是怎麼知道這個需要從這個bean中獲取配置資訊呢?我們看下PropertyPlaceholderConfigurer這個類的層次結構,如下圖: 

從上圖中我們可以看到PropertyPlaceholderConfigurer間接的繼承了BeanFactoryPostProcessor介面,這是一個很特別的介面,當spring載入任何實現了這個介面的bean的配置時,都會在bean工廠載入所有bean的配置之後執行postProcessBeanFactory方法。在PropertyResourceConfigurer類中實現了postProcessBeanFactory方法,在方法中先後調用了mergeProperties、convertProperties、processProperties這三個方法,分別得到配置,將得到的配置轉換為合適的類型,最後將配置內容告知BeanFactory。
正是通過實現BeanFactoryPostProcessor介面,BeanFactory會在實例化任何bean之前獲得配置資訊,從而能夠正確的解析bean描述文件中的變數引用。

public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {      try {          Properties mergedProps = this.mergeProperties();          this.convertProperties(mergedProps);          this.processProperties(beanFactory, mergedProps);      } catch (IOException var3) {          throw new BeanInitializationException("Could not load properties", var3);      }  }

自定義BeanFactoryPostProcessor

編寫實現了BeanFactoryPostProcessor介面的MyBeanFactoryPostProcessor的容器後處理器,如下程式碼:

public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {      public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {          System.out.println("對容器進行後處理。。。。");      }  }

然後在配置文件中註冊這個bean,如下:

<bean id="myPost" class="com.yhl.myspring.demo.applicationcontext.MyBeanFactoryPostProcessor"></bean>

最後編寫測試程式碼:

public class Test {      public static void main(String[] args) {          ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");            User user = (User)context.getBean("user");          System.out.println(user.getName());        }  }

激活BeanFactoryPostProcessor

在了解BeanFactoryPostProcessor的用法後我們便可以深入的研究BeanFactoryPostProcessor的調用過程了,其是在方法invokeBeanFactoryPostProcessors(beanFactory)中實現的,進入到方法內部:

public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {        // Invoke BeanDefinitionRegistryPostProcessors first, if any.      // 1、首先調用BeanDefinitionRegistryPostProcessors      Set<String> processedBeans = new HashSet<>();        // beanFactory是BeanDefinitionRegistry類型      if (beanFactory instanceof BeanDefinitionRegistry) {          BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;          // 定義BeanFactoryPostProcessor          List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();          // 定義BeanDefinitionRegistryPostProcessor集合          List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();            // 循環手動註冊的beanFactoryPostProcessors          for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {              // 如果是BeanDefinitionRegistryPostProcessor的實例話,則調用其postProcessBeanDefinitionRegistry方法,對bean進行註冊操作              if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {                  // 如果是BeanDefinitionRegistryPostProcessor類型,則直接調用其postProcessBeanDefinitionRegistry                  BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor;                  registryProcessor.postProcessBeanDefinitionRegistry(registry);                  registryProcessors.add(registryProcessor);              }              // 否則則將其當做普通的BeanFactoryPostProcessor處理,直接加入regularPostProcessors集合,以備後續處理              else {                  regularPostProcessors.add(postProcessor);              }          }            // Do not initialize FactoryBeans here: We need to leave all regular beans          // uninitialized to let the bean factory post-processors apply to them!          // Separate between BeanDefinitionRegistryPostProcessors that implement          // PriorityOrdered, Ordered, and the rest.          List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();            // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.          // 首先調用實現了PriorityOrdered(有限排序介面)的BeanDefinitionRegistryPostProcessors          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集合          registryProcessors.addAll(currentRegistryProcessors);          // 調用所有實現了PriorityOrdered的的BeanDefinitionRegistryPostProcessors的postProcessBeanDefinitionRegistry方法,註冊bean          invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);          // 清空currentRegistryProcessors,以備下次使用          currentRegistryProcessors.clear();            // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.          // 其次,調用實現了Ordered(普通排序介面)的BeanDefinitionRegistryPostProcessors          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集合          registryProcessors.addAll(currentRegistryProcessors);          // 調用所有實現了PriorityOrdered的的BeanDefinitionRegistryPostProcessors的postProcessBeanDefinitionRegistry方法,註冊bean          invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);          // 清空currentRegistryProcessors,以備下次使用          currentRegistryProcessors.clear();            // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.          // 最後,調用其他的BeanDefinitionRegistryPostProcessors          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集合              registryProcessors.addAll(currentRegistryProcessors);              // 調用其他的BeanDefinitionRegistryPostProcessors的postProcessBeanDefinitionRegistry方法,註冊bean              invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);              // 清空currentRegistryProcessors,以備下次使用              currentRegistryProcessors.clear();          }            // Now, invoke the postProcessBeanFactory callback of all processors handled so far.          // 調用所有BeanDefinitionRegistryPostProcessor(包括手動註冊和通過配置文件註冊)          // 和BeanFactoryPostProcessor(只有手動註冊)的回調函數-->postProcessBeanFactory          invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);          invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);      }        // 2、如果不是BeanDefinitionRegistry的實例,那麼直接調用其回調函數即可-->postProcessBeanFactory      else {          // Invoke factory processors registered with the context instance.          invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);      }        // Do not initialize FactoryBeans here: We need to leave all regular beans      // uninitialized to let the bean factory post-processors apply to them!      // 3、上面的程式碼已經處理完了所有的BeanDefinitionRegistryPostProcessors和手動註冊的BeanFactoryPostProcessor      // 接下來要處理通過配置文件註冊的BeanFactoryPostProcessor      // 首先獲取所有的BeanFactoryPostProcessor(注意:這裡獲取的集合會包含BeanDefinitionRegistryPostProcessors)      String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);        // Separate between BeanFactoryPostProcessors that implement PriorityOrdered, Ordered, and the rest.      // 這裡,將實現了PriorityOrdered,Ordered的處理器和其他的處理器區分開來,分別進行處理      // PriorityOrdered有序處理器      List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();      // Ordered有序處理器      List<String> orderedPostProcessorNames = new ArrayList<>();      // 無序處理器      List<String> nonOrderedPostProcessorNames = new ArrayList<>();      for (String ppName : postProcessorNames) {          // 判斷processedBeans是否包含當前處理器(processedBeans中的處理器已經被處理過);如果包含,則不做任何處理          if (processedBeans.contains(ppName)) {              // skip - already processed in first phase above          }          else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {              // 加入到PriorityOrdered有序處理器集合              priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));          }          else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {              // 加入到Ordered有序處理器集合              orderedPostProcessorNames.add(ppName);          }          else {              // 加入到無序處理器集合              nonOrderedPostProcessorNames.add(ppName);          }      }        // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.      // 首先調用實現了PriorityOrdered介面的處理器      sortPostProcessors(priorityOrderedPostProcessors, beanFactory);      invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);        // Next, invoke the BeanFactoryPostProcessors that implement Ordered.      // 其次,調用實現了Ordered介面的處理器      List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();      for (String postProcessorName : orderedPostProcessorNames) {          orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));      }      sortPostProcessors(orderedPostProcessors, beanFactory);      invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);        // Finally, invoke all other BeanFactoryPostProcessors.      // 最後,調用無序處理器      List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();      for (String postProcessorName : nonOrderedPostProcessorNames) {          nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));      }      invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);        // Clear cached merged bean definitions since the post-processors might have      // modified the original metadata, e.g. replacing placeholders in values...      // 清理元數據      beanFactory.clearMetadataCache();  }

循環遍歷  BeanFactoryPostProcessor 中的 postProcessBeanFactory 方法

private static void invokeBeanFactoryPostProcessors(          Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {        for (BeanFactoryPostProcessor postProcessor : postProcessors) {          postProcessor.postProcessBeanFactory(beanFactory);      }  }

註冊BeanPostProcessor

在上文中提到了BeanFactoryPostProcessor的調用,接下來我們就探索下BeanPostProcessor。但這裡並不是調用,而是註冊,真正的調用其實是在bean的實例化階段進行的,這是一個很重要的步驟,也是很多功能BeanFactory不知道的重要原因。spring中大部分功能都是通過後處理器的方式進行擴展的,這是spring框架的一個特寫,但是在BeanFactory中其實並沒有實現後處理器的自動註冊,所以在調用的時候如果沒有進行手動註冊其實是不能使用的。但是ApplicationContext中卻添加了自動註冊功能,如自定義一個後處理器:

public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {      public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {          System.out.println("befor");          return null;      }  }

然後在配置文件中添加bean的配置:

<bean class="com.yhl.myspring.demo.applicationcontext.MyInstantiationAwareBeanPostProcessor"/>

這樣的話再使用BeanFactory的方式進行載入的bean在載入時不會有任何改變的,而在使用ApplicationContext方式獲取的bean時就會列印出“before”,而這個特性就是咋registryBeanPostProcessor方法中完成的。
我們繼續深入分析registryBeanPostProcessors的方法實現:

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {      PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);  }  public static void registerBeanPostProcessors(          ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {        String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);        /*       * BeanPostProcessorChecker是一個普通的資訊列印,可能會有些情況當spring的配置中的後       * 處理器還沒有被註冊就已經開了bean的初始化,這時就會列印出BeanPostProcessorChecker中       * 設定的資訊       */      int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;      beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));        //使用PriorityOrdered來保證順序      List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();      List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();      //使用Ordered來保證順序      List<String> orderedPostProcessorNames = new ArrayList<>();      //無序BeanPostProcessor      List<String> nonOrderedPostProcessorNames = new ArrayList<>();      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的BeanPostProcessor      sortPostProcessors(priorityOrderedPostProcessors, beanFactory);      registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);        //註冊實現了Ordered的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);          }      }      sortPostProcessors(orderedPostProcessors, beanFactory);      registerBeanPostProcessors(beanFactory, orderedPostProcessors);        //註冊所有的無序的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);          }      }      registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);        //註冊所有的內部BeanFactoryProcessor      sortPostProcessors(internalPostProcessors, beanFactory);      registerBeanPostProcessors(beanFactory, internalPostProcessors);        // Re-register post-processor for detecting inner beans as ApplicationListeners,      //添加ApplicationListener探測器      beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));  }

我們可以看到先從容器中獲取所有類型為 BeanPostProcessor.class 的Bean的name數組,然後通過 BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); 獲取Bean的實例,最後通過 registerBeanPostProcessors(beanFactory, orderedPostProcessors);將獲取到的BeanPostProcessor實例添加到容器的屬性中,如下

private static void registerBeanPostProcessors(          ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {        for (BeanPostProcessor postProcessor : postProcessors) {          beanFactory.addBeanPostProcessor(postProcessor);      }  }    @Override  public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {      Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");      // Remove from old position, if any      this.beanPostProcessors.remove(beanPostProcessor);      // Track whether it is instantiation/destruction aware      if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {          this.hasInstantiationAwareBeanPostProcessors = true;      }      if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {          this.hasDestructionAwareBeanPostProcessors = true;      }      // Add to end of list      this.beanPostProcessors.add(beanPostProcessor);  }

可以看到將 beanPostProcessor 實例添加到容器的 beanPostProcessors 屬性中

初始化Message資源

該方法不是很重要,留在以後分析吧。。。

初始事件廣播器

初始化ApplicationEventMulticaster是在方法initApplicationEventMulticaster()中實現的,進入到方法體,如下:

protected void initApplicationEventMulticaster() {      ConfigurableListableBeanFactory beanFactory = getBeanFactory();      // 1、默認使用內置的事件廣播器,如果有的話.      // 我們可以在配置文件中配置Spring事件廣播器或者自定義事件廣播器      // 例如: <bean id="applicationEventMulticaster" class="org.springframework.context.event.SimpleApplicationEventMulticaster"></bean>      if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {          this.applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);      }      // 2、否則,新建一個事件廣播器,SimpleApplicationEventMulticaster是spring的默認事件廣播器      else {          this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);          beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);      }  }

通過源碼可以看到其實現邏輯與initMessageSource基本相同,其步驟如下:
(1)查找是否有name為applicationEventMulticaster的bean,如果有放到容器里,如果沒有,初始化一個系統默認的SimpleApplicationEventMulticaster放入容器
(2)查找手動設置的applicationListeners,添加到applicationEventMulticaster里
(3)查找定義的類型為ApplicationListener的bean,設置到applicationEventMulticaster
(4)初始化完成、對earlyApplicationEvents里的事件進行通知(此容器僅僅是廣播器未建立的時候保存通知資訊,一旦容器建立完成,以後均直接通知)
(5)在系統操作時候,遇到的各種bean的通知事件進行通知
可以看到的是applicationEventMulticaster是一個標準的觀察者模式,對於他內部的監聽者applicationListeners,每次事件到來都會一一獲取通知。

註冊監聽器

protected void registerListeners() {      // Register statically specified listeners first.      // 首先,註冊指定的靜態事件監聽器,在spring boot中有應用      for (ApplicationListener<?> listener : getApplicationListeners()) {          getApplicationEventMulticaster().addApplicationListener(listener);      }        // Do not initialize FactoryBeans here: We need to leave all regular beans      // uninitialized to let post-processors apply to them!      // 其次,註冊普通的事件監聽器      String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);      for (String listenerBeanName : listenerBeanNames) {          getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);      }        // Publish early application events now that we finally have a multicaster...      // 如果有早期事件的話,在這裡進行事件廣播      // 因為前期SimpleApplicationEventMulticaster尚未註冊,無法發布事件,      // 因此早期的事件會先存放在earlyApplicationEvents集合中,這裡把它們取出來進行發布      // 所以早期事件的發布時間節點是早於其他事件的      Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;      // 早期事件廣播器是一個Set<ApplicationEvent>集合,保存了無法發布的早期事件,當SimpleApplicationEventMulticaster      // 創建完之後隨即進行發布,同事也要將其保存的事件釋放      this.earlyApplicationEvents = null;      if (earlyEventsToProcess != null) {          for (ApplicationEvent earlyEvent : earlyEventsToProcess) {              getApplicationEventMulticaster().multicastEvent(earlyEvent);          }      }  }

我們來看一下Spring的事件監昕的簡單用法

定義監聽事件

public class TestEvent extends ApplicationonEvent {      public String msg;      public TestEvent (Object source ) {          super (source );      }      public TestEvent (Object source , String msg ) {          super(source);          this.msg = msg ;      }      public void print () {          System.out.println(msg) ;      }  }

定義監昕器

public class TestListener implement ApplicationListener {      public void onApplicationEvent (ApplicationEvent event ) {          if (event instanceof TestEvent ) {              TestEvent testEvent = (TestEvent) event ;              testEvent print () ;          }      }  }

添加配置文件

<bean id=” testListener” class=” com.test.event.TestListener ” />

測試

@Test  public void MyAopTest() {      ApplicationContext ac = new ClassPathXmlApplicationContext("spring-aop.xml");      TestEvent event = new TestEvent (“hello” ,”msg”) ;      context.publishEvent(event);  }

源碼分析

protected void publishEvent(Object event, ResolvableType eventType) {      Assert.notNull(event, "Event must not be null");      if (logger.isTraceEnabled()) {          logger.trace("Publishing event in " + getDisplayName() + ": " + event);      }        // Decorate event as an ApplicationEvent if necessary      ApplicationEvent applicationEvent;      //支援兩種事件1、直接繼承ApplicationEvent,2、其他時間,會被包裝為PayloadApplicationEvent,可以使用getPayload獲取真實的通知內容      if (event instanceof ApplicationEvent) {          applicationEvent = (ApplicationEvent) event;      }      else {          applicationEvent = new PayloadApplicationEvent<Object>(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) {          //如果有預製行添加到預製行,預製行在執行一次後被置為null,以後都是直接執行          this.earlyApplicationEvents.add(applicationEvent);      }      else {          //廣播event事件          getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);      }        // Publish event via parent context as well...      //父bean同樣廣播      if (this.parent != null) {          if (this.parent instanceof AbstractApplicationContext) {              ((AbstractApplicationContext) this.parent).publishEvent(event, eventType);          }          else {              this.parent.publishEvent(event);          }      }  }

查找所有的監聽者,依次遍歷,如果有執行緒池,利用執行緒池進行發送,如果沒有則直接發送,如果針對比較大的並發量,我們應該採用執行緒池模式,將發送通知和真正的業務邏輯進行分離

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

調用invokeListener

protected void invokeListener(ApplicationListener listener, ApplicationEvent event) {      ErrorHandler errorHandler = getErrorHandler();      if (errorHandler != null) {          try {              listener.onApplicationEvent(event);          }          catch (Throwable err) {              errorHandler.handleError(err);          }      }      else {          try {              listener.onApplicationEvent(event);          }          catch (ClassCastException ex) {              // Possibly a lambda-defined listener which we could not resolve the generic event type for              LogFactory.getLog(getClass()).debug("Non-matching event type for listener: " + listener, ex);          }      }  }

初始化其他的單例Bean(非延遲載入的)

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {      // Initialize conversion service for this context.      // 判斷有無ConversionService(bean屬性類型轉換服務介面),並初始化      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));      }        //      // Register a default embedded value resolver if no bean post-processor      // (such as a PropertyPlaceholderConfigurer bean) registered any before:      // at this point, primarily for resolution in annotation attribute values.      // 如果beanFactory中不包含EmbeddedValueResolver,則向其中添加一個EmbeddedValueResolver      // EmbeddedValueResolver-->解析bean中的佔位符和表達式      if (!beanFactory.hasEmbeddedValueResolver()) {          beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));      }        // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.      // 初始化LoadTimeWeaverAware類型的bean      // LoadTimeWeaverAware-->載入Spring Bean時織入第三方模組,如AspectJ      String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);      for (String weaverAwareName : weaverAwareNames) {          getBean(weaverAwareName);      }        // Stop using the temporary ClassLoader for type matching.      // 釋放臨時類載入器      beanFactory.setTempClassLoader(null);        // Allow for caching all bean definition metadata, not expecting further changes.      // 凍結快取的BeanDefinition元數據      beanFactory.freezeConfiguration();        // Instantiate all remaining (non-lazy-init) singletons.      // 初始化其他的非延遲載入的單例bean      beanFactory.preInstantiateSingletons();  }

我們重點看  beanFactory.preInstantiateSingletons();

@Override  public void preInstantiateSingletons() throws BeansException {      if (logger.isTraceEnabled()) {          logger.trace("Pre-instantiating singletons in " + this);      }        // Iterate over a copy to allow for init methods which in turn register new bean definitions.      // While this may not be part of the regular factory bootstrap, it does otherwise work fine.      List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);        // 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);              }          }      }    }

完成刷新過程,通知生命周期處理器lifecycleProcessor刷新過程,同時發出ContextRefreshEvent通知

protected void finishRefresh() {      // Clear context-level resource caches (such as ASM metadata from scanning).      // 清空資源快取      clearResourceCaches();        // Initialize lifecycle processor for this context.      // 初始化生命周期處理器      initLifecycleProcessor();        // Propagate refresh to lifecycle processor first.      // 調用生命周期處理器的onRefresh方法      getLifecycleProcessor().onRefresh();        // Publish the final event.      // 推送容器刷新事件      publishEvent(new ContextRefreshedEvent(this));        // Participate in LiveBeansView MBean, if active.      LiveBeansView.registerApplicationContext(this);  }