91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Spring IOC 容器啟動的示例分析

發布時間:2021-08-25 09:14:08 來源:億速云 閱讀:104 作者:小新 欄目:編程語言

這篇文章給大家分享的是有關Spring IOC 容器啟動的示例分析的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。

使用 Spring 時,XML 和注解是使用得最多的兩種配置方式,雖然是兩種完全不同的配置方式,但對于 IOC 容器來說,兩種方式的不同主要是在 BeanDefinition 的解析上。而對于核心的容器啟動流程,仍然是一致的。

AbstractApplicationContext 的 refresh 方法實現了 IOC 容器啟動的主要邏輯,啟動流程中的關鍵步驟在源碼中也可以對應到獨立的方法。接下來以  AbstractApplicationContext 的實現類  ClassPathXmlApplicationContext 為主 ,并對比其另一個實現類 AnnotationConfigApplicationContext , 解讀 IOC 容器的啟動過程。

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 的關系

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

Spring IOC 容器啟動的示例分析 

ApplicationContext 繼承樹( 高清大圖 )

Spring IOC 容器啟動的示例分析 

BeanFactory 繼承樹( 高清大圖 )

ApplicationContext 是 IOC 容器的承載體,而  BeanFactory 是操作這個容器的工具,兩者關系緊密,相互協作。 refresh 方法實現了 ApplicationContext 和 BeanFactory 相互協作的主要過程,不同之處主要在子類  AbstractRefreshableApplicationContext 和 GenericApplicationContext 中實現,兩者使用的 BeanFactory 都為 DefaultListableBeanFactory , DefaultListableBeanFactory 的定義如下:

DefaultListableBeanFactory :

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
  implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable

可見 DefaultListableBeanFactory 實現了  ConfigurableListableBeanFactory ,意味著是可配置,可遍歷的,至于為什么可以,讓我們繼續往下尋找找答案。

BeanDefinition 的獲取

DefaultListableBeanFactory 中使用 Map 結構保存所有的 BeanDefinition 信息:

DefaultListableBeanFactory :

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


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

AnnotationConfigApplicationContext 中的解析
通過 BeanDefinitionScanner 掃描 Bean 聲明,解析為 BeanDefinition 并由 BeanDefinitionRegistry 注冊到 BeanFactory 中。 入口: AnnotationConfigApplicationContext 的構造函數。

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

AbstractApplicationContext :

protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException

可見是一個抽象方法,具體實現在子類中。只有 "Refreshable" 的 BeanFactory 才會在該方法中實現具體操作,如  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);
 }
 }

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

主流程分析

refresh 方法在  AbstractApplicationContext 中定義,其中的  obtainFreshBeanFactory 方法調用了 getBeanFactory 方法,該方法用于獲取  BeanFactory ,這里為  DefaultListableBeanFactory ,接下來無特別說明,大部分的方法和變量都將取自  AbstractApplicationContext 和   DefaultListableBeanFactory 。 

Spring IOC 容器啟動的示例分析 

高清大圖

BeanPostProcessor

BeanPostProcessor 接口讓開發者在 IOC 容器對 Bean 進行實例化時收到回調( postProcessAfterInitialization 和  postProcessBeforeInitialization 方法)。spring 框架內部的許多通知( Aware )就是通過這個接口實現,如  ApplicationContextAwareProcessor ,  ServletContextAwareProcessor ,他們的實現會在  postProcessBeforeInitialization 方法中進行檢查,若實現了特定接口,就會調用 Aware 的回調方法,給予通知:

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 方法中,子類可以通過 beanFactory.addBeanPostProcessor 方法添加自己的 BeanPostProcessor 到 beanFactory 中,最終將保存到 BeanFactory 的  beanPostProcessors (實為 CopyOnWriteArrayList ) 中。 prepareBeanFactory 和 registerBeanPostProcessors 方法是集中實例化并添加這些 Bean 的地方。

BeanFactoryPostProcessor 和 BeanDefinitionRegistryPostProcessor
從"BeanDefinition 的獲取"的介紹可以知道 BeanDefinitionRegistry 用于將  BeanDefinition 注冊到 BeanFactory 中, GenericApplicationContext 和  DefaultListableBeanFactory 都實現了該接口, GenericApplicationContext 中的實現直接調用了 beanFactory 的實現。

BeanFactoryPostProcessor 和 BeanDefinitionRegistryPostProcessor 與  BeanPostProcessor 類似,但從他們的命名就可以看出,所針對的目標不同,分別是 BeanFactory 和  BeanDefinitionRegistry: 1 BeanFactoryPostProcessor 回調讓開發者有機會在 BeanFactory 已經初始化好的情況下對 BeanFactory 的一些屬性進行覆蓋,或是對  beanDefinitionMap 中的  BeanDefinition 進行修改。 2 BeanDefinitionRegistryPostProcessor 則讓開發者可以繼續添加  BeanDefinition 到 BeanFactory 中。

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

對于這部分 Bean 的實例化和進行回調有一定的優先級規則。 PriorityOrdered 繼承自 Ordered 接口,實現了  PriorityOrdered 的  BeanDefinitionRegistryPostProcessor 將最先被實例化并調用,然后同樣的規則來回調實現了  BeanFactoryPostProcessor 的 Bean: PriorityOrdered > Ordered > 未實現 Ordered 的

在 registerBeanPostProcessors 方法中對 BeanPostProcessor 的實例化也有這樣的優先級規則: PriorityOrdered > Ordered > 未實現 Ordered 的 > MergedBeanDefinitionPostProcessor

ApplicationEventMulticaster

在 initApplicationEventMulticaster 中會對  ApplicationEventMulticaster 進行初始化: 首先會檢查是否已經有了 ApplicationEventMulticaster 的  BeanDefinition (在  beanDefinitionMap 中檢查),有就讓容器進行實例化,沒有就使用框架默認的  ApplicationEventMulticaster (即 SimpleApplicationEventMulticaster ),先實例化,然后注冊到容器中( MessageSource 在 initMessageSource 方法中也是同樣的方式進行初始化)。

事件的起始發送處將事件包裝為 ApplicationEvent ,并通過  ApplicationEventPublisher 提交給  ApplicationEventMulticaster , ApplicationEventMulticaster 會將事件廣播給  ApplicationListener ,處理最終的分發。

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

finishRefresh 方法中有一個對  ContextRefreshedEvent 事件的廣播可以作為參考,最終事件會由  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 中如何得到這個 ApplicationEventPublisher 呢? ApplicationContext 的定義如下:

ApplicationContext :

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

可見 ApplicationContext 繼承了  ApplicationEventPublisher ,這就說明  AbstractApplicationContext 也是一個  ApplicationEventPublisher 。在我們自己的 Bean 中通過實現  ApplicationEventPublisherAware ,我們就能通過  setApplicationEventPublisher 回調得到  ApplicationEventPublisher 。

上面我們提到 spring 的許多 Aware 是通過  BeanPostProcessor 實現的, 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 容器在實例化我們的 Bean 時會調用 ApplicationContextAwareProcessor . postProcessBeforeInitialization 方法,該方法會檢查我們的 Bean,我們的 Bean 如果實現了  ApplicationEventPublisherAware ,那么就會回調  setApplicationEventPublisher 方法將  applicationContext (即 ApplicationEventPublisher ) 傳給我們,我們就能夠發布事件。

BeanFactory.getBean

BeanFactory 的幾個重載了的 getBean 方法是 Bean 最終進行實例化的地方, registerBeanPostProcessors ,  invokeBeanFactoryPostProcessors 和  finishBeanFactoryInitialization 方法都調用了 getBean 方法對一些特定 Bean 進行了實例化。

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

總結

spring IOC 容器的啟動步驟可總結如下: 1 初始化 ApplicationContext 環境屬性的初始化和驗證,啟動時間記錄和相關標記設置,應用事件和監聽者的初始化。

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

3 初始化 BeanFactory 準備好 BeanFactory 以供 ApplicationContext 進行使用,對接下來將要使用到的 Bean 進行實例化,資源進行準備,屬性進行設置。

4 注冊 BeanPostProcessors BeanPostProcessors 是進行擴展的關鍵組件,需要在該步驟中進行注冊,可分為兩種類型: 一種是框架使用者提供的,用于特定業務功能的,另一種是框架開發者提供的,用于擴展框架功能。

5 調用 BeanDefinitionRegistryPostProcessor BeanDefinitionRegistryPostProcessor 是一種功能增強,可以在這個步驟添加新的  BeanDefinition 到 BeanFactory 中。

6 調用 BeanFactoryPostProcessor BeanFactoryPostProcessor 是一種功能增強,可以在這個步驟對已經完成初始化的 BeanFactory 進行屬性覆蓋,或是修改已經注冊到 BeanFactory 的  BeanDefinition 。

7 初始化 MessageSource 和  ApplicationEventMulticaster MessageSource 用于處理國際化資源, ApplicationEventMulticaster 是應用事件廣播器,用于分發應用事件給監聽者。

8 初始化其他 Bean 和進行其他的的上下文初始化 主要用于擴展

9 注冊 ApplicationListene 將  ApplicationListene 注冊到 BeanFactory 中,以便后續的事件分發

10 實例化剩余的 Bean 單例 步驟 4 到 9 都對一些特殊的 Bean 進行了實例化,這里需要對所有剩余的單例 Bean 進行實例化

11 啟動完成 資源回收,分發"刷新完成"事件。

感謝各位的閱讀!關于“Spring IOC 容器啟動的示例分析”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

曲靖市| 绵阳市| 云龙县| 延安市| 洛宁县| 沭阳县| 新疆| 旬邑县| 沙坪坝区| 尼木县| 西平县| 潮州市| 白城市| 昌黎县| 甘孜县| 兰西县| 威宁| 锡林郭勒盟| 玉树县| 建宁县| 湖北省| 仁布县| 扬州市| 横峰县| 海口市| 新绛县| 大田县| 连城县| 桑植县| 应城市| 津市市| 广南县| 永德县| 莒南县| 赣榆县| 六盘水市| 开鲁县| 凤台县| 洛阳市| 东城区| 滨州市|