欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Spring IOC 容器啟動(dòng)流程分析

 更新時(shí)間:2019年08月29日 14:12:40   作者:CAFE_BABE  
這篇文章主要介紹了Spring IOC 容器啟動(dòng)流程分析,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

使用 Spring 時(shí),XML 和注解是使用得最多的兩種配置方式,雖然是兩種完全不同的配置方式,但對(duì)于 IOC 容器來(lái)說(shuō),兩種方式的不同主要是在 BeanDefinition 的解析上。而對(duì)于核心的容器啟動(dòng)流程,仍然是一致的。

AbstractApplicationContext 的 refresh 方法實(shí)現(xiàn)了 IOC 容器啟動(dòng)的主要邏輯,啟動(dòng)流程中的關(guān)鍵步驟在源碼中也可以對(duì)應(yīng)到獨(dú)立的方法。接下來(lái)以  AbstractApplicationContext 的實(shí)現(xiàn)類(lèi)  ClassPathXmlApplicationContext 為主 ,并對(duì)比其另一個(gè)實(shí)現(xiàn)類(lèi) AnnotationConfigApplicationContext , 解讀 IOC 容器的啟動(dòng)過(guò)程。

AbstractApplicationContext.refresh

@Override
 public void refresh() throws BeansException, IllegalStateException {
 synchronized (this.startupShutdownMonitor) {
  // Prepare this context for refreshing.
  prepareRefresh();

  // Tell the subclass to refresh the internal bean factory.
  ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

  // Prepare the bean factory for use in this context.
  prepareBeanFactory(beanFactory);

  try {
  // Allows post-processing of the bean factory in context subclasses.
  postProcessBeanFactory(beanFactory);

  // Invoke factory processors registered as beans in the context.
  invokeBeanFactoryPostProcessors(beanFactory);

  // Register bean processors that intercept bean creation.
  registerBeanPostProcessors(beanFactory);

  // Initialize message source for this context.
  initMessageSource();

  // Initialize event multicaster for this context.
  initApplicationEventMulticaster();

  // Initialize other special beans in specific context subclasses.
  onRefresh();

  // Check for listener beans and register them.
  registerListeners();

  // Instantiate all remaining (non-lazy-init) singletons.
  finishBeanFactoryInitialization(beanFactory);

  // Last step: publish corresponding event.
  finishRefresh();
  }

  // ...
 }
 }

ApplicationContext 和 BeanFactory 的關(guān)系

ClassPathXmlApplicationContext 和  AnnotationConfigApplicationContext 的繼承樹(shù)如下所示。兩者都繼承自  AbstractApplicationContext 。

 

ApplicationContext 繼承樹(shù)( 高清大圖 )

 

BeanFactory 繼承樹(shù)( 高清大圖 )

ApplicationContext 是 IOC 容器的承載體,而  BeanFactory 是操作這個(gè)容器的工具,兩者關(guān)系緊密,相互協(xié)作。 refresh 方法實(shí)現(xiàn)了 ApplicationContext 和 BeanFactory 相互協(xié)作的主要過(guò)程,不同之處主要在子類(lèi)  AbstractRefreshableApplicationContext 和 GenericApplicationContext 中實(shí)現(xiàn),兩者使用的 BeanFactory 都為 DefaultListableBeanFactory , DefaultListableBeanFactory 的定義如下:

DefaultListableBeanFactory :

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
  implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable

可見(jiàn) DefaultListableBeanFactory 實(shí)現(xiàn)了  ConfigurableListableBeanFactory ,意味著是可配置,可遍歷的,至于為什么可以,讓我們繼續(xù)往下尋找找答案。

BeanDefinition 的獲取

DefaultListableBeanFactory 中使用 Map 結(jié)構(gòu)保存所有的 BeanDefinition 信息:

DefaultListableBeanFactory :

private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);


ClassPathXmlApplicationContext 中的解析
使用 BeanDefinitionDocumentReader (可參看 DefaultBeanDefinitionDocumentReader.processBeanDefinition 方法) 將 xml 中的 bean 解析為 BeanDefinition , 然后由 BeanDefinitionRegistry 注冊(cè)到 BeanFactory 中。 入口: AbstractApplicationContext.refreshBeanFactory (在 refresh 中調(diào)用)

AnnotationConfigApplicationContext 中的解析
通過(guò) BeanDefinitionScanner 掃描 Bean 聲明,解析為 BeanDefinition 并由 BeanDefinitionRegistry 注冊(cè)到 BeanFactory 中。 入口: AnnotationConfigApplicationContext 的構(gòu)造函數(shù)。

為什么 ClassPathXmlApplicationContext 的入口是在 refreshBeanFactory 方法中 ?
AbstractApplicationContext.refreshBeanFactory 定義如下:

AbstractApplicationContext :

protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException

可見(jiàn)是一個(gè)抽象方法,具體實(shí)現(xiàn)在子類(lèi)中。只有 "Refreshable" 的 BeanFactory 才會(huì)在該方法中實(shí)現(xiàn)具體操作,如  AbstractRefreshableApplicationContext :

AbstractRefreshableApplicationContext :

@Override
 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);
 }
 }

可見(jiàn) AbstractRefreshableApplicationContext.``refreshBeanFactory 方法會(huì)檢查 BeanFactory 是否已經(jīng)存在( hasBeanFactory ),已經(jīng)存在就先銷(xiāo)毀所有的 Bean( destoryBeans )并關(guān)閉( closeBeanFactory ) BeanFactory ,然后再創(chuàng)建( createBeanFactory )新的。 而  GenericApplicationContext.refreshBeanFactory 中會(huì)檢查是否為第一次調(diào)用,不是就拋出異常,不執(zhí)行其他邏輯,即  GenericApplicationContext 不是 "Refreshable"的。

主流程分析

refresh 方法在  AbstractApplicationContext 中定義,其中的  obtainFreshBeanFactory 方法調(diào)用了 getBeanFactory 方法,該方法用于獲取  BeanFactory ,這里為  DefaultListableBeanFactory ,接下來(lái)無(wú)特別說(shuō)明,大部分的方法和變量都將取自  AbstractApplicationContext 和   DefaultListableBeanFactory 。 

 

高清大圖

BeanPostProcessor

BeanPostProcessor 接口讓開(kāi)發(fā)者在 IOC 容器對(duì) Bean 進(jìn)行實(shí)例化時(shí)收到回調(diào)( postProcessAfterInitialization 和  postProcessBeforeInitialization 方法)。spring 框架內(nèi)部的許多通知( Aware )就是通過(guò)這個(gè)接口實(shí)現(xiàn),如  ApplicationContextAwareProcessor ,  ServletContextAwareProcessor ,他們的實(shí)現(xiàn)會(huì)在  postProcessBeforeInitialization 方法中進(jìn)行檢查,若實(shí)現(xiàn)了特定接口,就會(huì)調(diào)用 Aware 的回調(diào)方法,給予通知:

ServletContextAwareProcessor :

@Override
 public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
 if (getServletContext() != null && bean instanceof ServletContextAware) {
  ((ServletContextAware) bean).setServletContext(getServletContext());
 }
 if (getServletConfig() != null && bean instanceof ServletConfigAware) {
  ((ServletConfigAware) bean).setServletConfig(getServletConfig());
 }
 return bean;
 }

在 postProcessBeanFactory 方法中,子類(lèi)可以通過(guò) beanFactory.addBeanPostProcessor 方法添加自己的 BeanPostProcessor 到 beanFactory 中,最終將保存到 BeanFactory 的  beanPostProcessors (實(shí)為 CopyOnWriteArrayList ) 中。 prepareBeanFactory 和 registerBeanPostProcessors 方法是集中實(shí)例化并添加這些 Bean 的地方。

BeanFactoryPostProcessor 和 BeanDefinitionRegistryPostProcessor
從"BeanDefinition 的獲取"的介紹可以知道 BeanDefinitionRegistry 用于將  BeanDefinition 注冊(cè)到 BeanFactory 中, GenericApplicationContext 和  DefaultListableBeanFactory 都實(shí)現(xiàn)了該接口, GenericApplicationContext 中的實(shí)現(xiàn)直接調(diào)用了 beanFactory 的實(shí)現(xiàn)。

BeanFactoryPostProcessor 和 BeanDefinitionRegistryPostProcessor 與  BeanPostProcessor 類(lèi)似,但從他們的命名就可以看出,所針對(duì)的目標(biāo)不同,分別是 BeanFactory 和  BeanDefinitionRegistry: 1 BeanFactoryPostProcessor 回調(diào)讓開(kāi)發(fā)者有機(jī)會(huì)在 BeanFactory 已經(jīng)初始化好的情況下對(duì) BeanFactory 的一些屬性進(jìn)行覆蓋,或是對(duì)  beanDefinitionMap 中的  BeanDefinition 進(jìn)行修改。 2 BeanDefinitionRegistryPostProcessor 則讓開(kāi)發(fā)者可以繼續(xù)添加  BeanDefinition 到 BeanFactory 中。

具體邏輯在 invokeBeanFactoryPostProcessors 中實(shí)現(xiàn),這里首先會(huì)將所有實(shí)現(xiàn)了 BeanFactoryPostProcessors 的 Bean 實(shí)例化,然后調(diào)用其回調(diào)方法( postProcessBeanDefinitionRegistry 或  postProcessBeanFactory 方法)。

對(duì)于這部分 Bean 的實(shí)例化和進(jìn)行回調(diào)有一定的優(yōu)先級(jí)規(guī)則。 PriorityOrdered 繼承自 Ordered 接口,實(shí)現(xiàn)了  PriorityOrdered 的  BeanDefinitionRegistryPostProcessor 將最先被實(shí)例化并調(diào)用,然后同樣的規(guī)則來(lái)回調(diào)實(shí)現(xiàn)了  BeanFactoryPostProcessor 的 Bean: PriorityOrdered > Ordered > 未實(shí)現(xiàn) Ordered 的

在 registerBeanPostProcessors 方法中對(duì) BeanPostProcessor 的實(shí)例化也有這樣的優(yōu)先級(jí)規(guī)則: PriorityOrdered > Ordered > 未實(shí)現(xiàn) Ordered 的 > MergedBeanDefinitionPostProcessor

ApplicationEventMulticaster

在 initApplicationEventMulticaster 中會(huì)對(duì)  ApplicationEventMulticaster 進(jìn)行初始化: 首先會(huì)檢查是否已經(jīng)有了 ApplicationEventMulticaster 的  BeanDefinition (在  beanDefinitionMap 中檢查),有就讓容器進(jìn)行實(shí)例化,沒(méi)有就使用框架默認(rèn)的  ApplicationEventMulticaster (即 SimpleApplicationEventMulticaster ),先實(shí)例化,然后注冊(cè)到容器中( MessageSource 在 initMessageSource 方法中也是同樣的方式進(jìn)行初始化)。

事件的起始發(fā)送處將事件包裝為 ApplicationEvent ,并通過(guò)  ApplicationEventPublisher 提交給  ApplicationEventMulticaster , ApplicationEventMulticaster 會(huì)將事件廣播給  ApplicationListener ,處理最終的分發(fā)。

AbstractApplicationEventMulticaster 中的 applicationListeners( 實(shí)為 LinkedHashSet<ApplicationListener>) 變量保存了所有的廣播接收者, registerListeners 方法會(huì)將所有的  ApplicationListener 添加到該集合中。

finishRefresh 方法中有一個(gè)對(duì)  ContextRefreshedEvent 事件的廣播可以作為參考,最終事件會(huì)由  multicastEvent 方法處理:

SimpleApplicationEventMulticaster.multicastEvent

@Override
 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);
  }
 }
 }

那么在我們自己的 Bean 中如何得到這個(gè) ApplicationEventPublisher 呢? ApplicationContext 的定義如下:

ApplicationContext :

public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
 MessageSource, ApplicationEventPublisher, ResourcePatternResolver {

可見(jiàn) ApplicationContext 繼承了  ApplicationEventPublisher ,這就說(shuō)明  AbstractApplicationContext 也是一個(gè)  ApplicationEventPublisher 。在我們自己的 Bean 中通過(guò)實(shí)現(xiàn)  ApplicationEventPublisherAware ,我們就能通過(guò)  setApplicationEventPublisher 回調(diào)得到  ApplicationEventPublisher 。

上面我們提到 spring 的許多 Aware 是通過(guò)  BeanPostProcessor 實(shí)現(xiàn)的, ApplicationEventPublisherAware 也不例外:

ApplicationContextAwareProcessor :

@Override
 @Nullable
 public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
 // ...
    if (bean instanceof Aware) {
  if (bean instanceof EnvironmentAware) {
  ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
  }
  if (bean instanceof EmbeddedValueResolverAware) {
  ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
  }
  if (bean instanceof ResourceLoaderAware) {
  ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
  }
  if (bean instanceof ApplicationEventPublisherAware) {
  ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
  }
  if (bean instanceof MessageSourceAware) {
  ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
  }
  if (bean instanceof ApplicationContextAware) {
  ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
  }
 }
    // ...
 }

IOC 容器在實(shí)例化我們的 Bean 時(shí)會(huì)調(diào)用 ApplicationContextAwareProcessor . postProcessBeforeInitialization 方法,該方法會(huì)檢查我們的 Bean,我們的 Bean 如果實(shí)現(xiàn)了  ApplicationEventPublisherAware ,那么就會(huì)回調(diào)  setApplicationEventPublisher 方法將  applicationContext (即 ApplicationEventPublisher ) 傳給我們,我們就能夠發(fā)布事件。

BeanFactory.getBean

BeanFactory 的幾個(gè)重載了的 getBean 方法是 Bean 最終進(jìn)行實(shí)例化的地方, registerBeanPostProcessors ,  invokeBeanFactoryPostProcessors 和  finishBeanFactoryInitialization 方法都調(diào)用了 getBean 方法對(duì)一些特定 Bean 進(jìn)行了實(shí)例化。

finishBeanFactoryInitialization 中通過(guò)調(diào)用 BeanFactory 的  preInstantiateSingletons 對(duì)單例 Bean 進(jìn)行實(shí)例化。 BeanFactory 和  BeanDefinition 都具有父子的概念,在子級(jí)找不到指定的 Bean 時(shí)將一直往上(父級(jí))找,找到就進(jìn)行實(shí)例化

總結(jié)

spring IOC 容器的啟動(dòng)步驟可總結(jié)如下: 1 初始化 ApplicationContext 環(huán)境屬性的初始化和驗(yàn)證,啟動(dòng)時(shí)間記錄和相關(guān)標(biāo)記設(shè)置,應(yīng)用事件和監(jiān)聽(tīng)者的初始化。

2 準(zhǔn)備好容器中的 BeanDefinition (eager-initializing beans) 對(duì) BeanDefinition 的解析、掃描和注冊(cè), BeanDefinition 的掃描和注冊(cè)大致可以分為 XML 和注解兩種,兩種方式各自使用的組件有所不同,該步驟的時(shí)間也可以在最前面。

3 初始化 BeanFactory 準(zhǔn)備好 BeanFactory 以供 ApplicationContext 進(jìn)行使用,對(duì)接下來(lái)將要使用到的 Bean 進(jìn)行實(shí)例化,資源進(jìn)行準(zhǔn)備,屬性進(jìn)行設(shè)置。

4 注冊(cè) BeanPostProcessors BeanPostProcessors 是進(jìn)行擴(kuò)展的關(guān)鍵組件,需要在該步驟中進(jìn)行注冊(cè),可分為兩種類(lèi)型: 一種是框架使用者提供的,用于特定業(yè)務(wù)功能的,另一種是框架開(kāi)發(fā)者提供的,用于擴(kuò)展框架功能。

5 調(diào)用 BeanDefinitionRegistryPostProcessor BeanDefinitionRegistryPostProcessor 是一種功能增強(qiáng),可以在這個(gè)步驟添加新的  BeanDefinition 到 BeanFactory 中。

6 調(diào)用 BeanFactoryPostProcessor BeanFactoryPostProcessor 是一種功能增強(qiáng),可以在這個(gè)步驟對(duì)已經(jīng)完成初始化的 BeanFactory 進(jìn)行屬性覆蓋,或是修改已經(jīng)注冊(cè)到 BeanFactory 的  BeanDefinition 。

7 初始化 MessageSource 和  ApplicationEventMulticaster MessageSource 用于處理國(guó)際化資源, ApplicationEventMulticaster 是應(yīng)用事件廣播器,用于分發(fā)應(yīng)用事件給監(jiān)聽(tīng)者。

8 初始化其他 Bean 和進(jìn)行其他的的上下文初始化 主要用于擴(kuò)展

9 注冊(cè) ApplicationListene 將  ApplicationListene 注冊(cè)到 BeanFactory 中,以便后續(xù)的事件分發(fā)

10 實(shí)例化剩余的 Bean 單例 步驟 4 到 9 都對(duì)一些特殊的 Bean 進(jìn)行了實(shí)例化,這里需要對(duì)所有剩余的單例 Bean 進(jìn)行實(shí)例化

11 啟動(dòng)完成 資源回收,分發(fā)"刷新完成"事件。

總結(jié)

以上所述是小編給大家介紹的Spring IOC 容器啟動(dòng)流程分析,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
如果你覺(jué)得本文對(duì)你有幫助,歡迎轉(zhuǎn)載,煩請(qǐng)注明出處,謝謝!

相關(guān)文章

  • Java ArrayList遍歷修改代碼實(shí)例解析

    Java ArrayList遍歷修改代碼實(shí)例解析

    這篇文章主要介紹了Java ArrayList遍歷修改代碼實(shí)例解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07
  • Java中的HashMap源碼分析

    Java中的HashMap源碼分析

    這篇文章主要介紹了Java中的HashMap源碼分析,散列表是根據(jù)關(guān)鍵碼值(Key?value)而直接進(jìn)行訪(fǎng)問(wèn)的數(shù)據(jù)結(jié)構(gòu),也就是說(shuō),它通過(guò)把關(guān)鍵碼值映射到表中一個(gè)位置來(lái)訪(fǎng)問(wèn)記錄,以加快查找的速度,這個(gè)映射函數(shù)叫做散列函數(shù),存放記錄的數(shù)組叫做散列表,需要的朋友可以參考下
    2023-09-09
  • IDEA編寫(xiě)JavaWeb出現(xiàn)亂碼問(wèn)題解決方案

    IDEA編寫(xiě)JavaWeb出現(xiàn)亂碼問(wèn)題解決方案

    這篇文章主要介紹了IDEA編寫(xiě)JavaWeb出現(xiàn)亂碼問(wèn)題解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-09-09
  • 透徹理解Java中Synchronized(對(duì)象鎖)和Static Synchronized(類(lèi)鎖)的區(qū)別

    透徹理解Java中Synchronized(對(duì)象鎖)和Static Synchronized(類(lèi)鎖)的區(qū)別

    這篇文章主要介紹了Java中Synchronized(對(duì)象鎖)和Static Synchronized(類(lèi)鎖)的區(qū)別,希望對(duì)大家有所幫助,一起跟隨小編過(guò)來(lái)看看吧
    2018-05-05
  • SpringBoot自動(dòng)配置與啟動(dòng)流程詳細(xì)分析

    SpringBoot自動(dòng)配置與啟動(dòng)流程詳細(xì)分析

    這篇文章主要介紹了SpringBoot自動(dòng)配置原理分析,SpringBoot是我們經(jīng)常使用的框架,那么你能不能針對(duì)SpringBoot實(shí)現(xiàn)自動(dòng)配置做一個(gè)詳細(xì)的介紹。如果可以的話(huà),能不能畫(huà)一下實(shí)現(xiàn)自動(dòng)配置的流程圖。牽扯到哪些關(guān)鍵類(lèi),以及哪些關(guān)鍵點(diǎn)
    2022-11-11
  • 深入學(xué)習(xí)Spring Cloud-Ribbon

    深入學(xué)習(xí)Spring Cloud-Ribbon

    這篇文章主要介紹了Spring Cloud-Ribbon的相關(guān)知識(shí),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友一起看看吧
    2021-03-03
  • Java中的Set集合源碼詳細(xì)解讀

    Java中的Set集合源碼詳細(xì)解讀

    這篇文章主要介紹了Java中的Set集合源碼詳細(xì)解讀,Set注重獨(dú)一無(wú)二的性質(zhì),該體系集合用于存儲(chǔ)無(wú)序(存入和取出的順序不一定相同)元素, 值不能重復(fù),需要的朋友可以參考下
    2023-11-11
  • 如何基于http代理解決Java固定ip問(wèn)題

    如何基于http代理解決Java固定ip問(wèn)題

    這篇文章主要介紹了如何基于http代理解決Java固定ip問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-03-03
  • JDK完全卸載超詳細(xì)步驟

    JDK完全卸載超詳細(xì)步驟

    這篇文章主要給大家介紹了關(guān)于JDK完全卸載超詳細(xì)步驟的相關(guān)資料,在安裝JDK之前,最好將原來(lái)可能安裝過(guò)的JDK卸載掉,以免影響到新JDK的使用,需要的朋友可以參考下
    2023-08-08
  • java web圖片上傳和文件上傳實(shí)例詳解

    java web圖片上傳和文件上傳實(shí)例詳解

    這篇文章主要介紹了java web圖片上傳和文件上傳實(shí)例詳解的相關(guān)資料,這里提供了兩種方法及示例代碼,需要的朋友可以參考下
    2016-11-11

最新評(píng)論