ApplicationContext容器

ApplicationContext容器

1.概述

      ApplicationContext接口代表了一個Spring容器,它主要負責實例化、配置和組裝bean。ApplicationContext接口間接繼承了BeanFactory接口,相較于BeanFactory一些基本的容器功能,ApplicationContext接口是在BeanFactory接口基礎上進行了擴展,增加了國際化、事件廣播、獲取資源等一些新的功能。

2.ApplicationContext系列類圖

      從以上類圖中可以看出,ApplicationContext接口的派生體系,是一個非常龐大的家族。

  • FileSystemXmlApplicationContext:默認從文件系統中加載bean定義信息的ApplicationContext實現。
  • ClassPathXmlApplicationContext:默認從ClassPath中加載bean定義信息的ApplicationContext實現。
  • XmlWebApplicationContext:專門用于Web應用程序的ApplicationContext實現。SpringMVC 中默認使用的容器。
  • AnnotationConfigApplicationContext:是一個基于注解配置類的ApplicationContext實現。SpringBoot 中默認使用的容器。
  • AnnotationConfigServletWebServerApplicationContext:是SpringBoot一個基于注解配置類的servlet web應用程序的ApplicationContext實現。容器中會一個內置的servlet 服務器。
  • AnnotationConfigReactiveWebServerApplicationContext:是SpringBoot一個基于基于注解配置類的reactive web應用程序的ApplicationContext實現。容器中會一個內置的reactive 服務器。

3.refresh()方法

3.1概述

      refresh方法是Spring容器中一個非常核心的方法。經過refresh方法后,一個完整的Ioc容器已經創建完成。refresh方法是在ConfigurableApplicationContext接口定義的,而給出具體這個方法實現的是在AbstractApplicationContext的類中。

      從refresh方法的源碼可以發現,refresh方法中調用了12個子方法。這12個子方法其實就是Spring創建Ioc容器的12個步驟。

      refresh方法其實是使用了模版方法模式。模板方法模式定義一個操作中算法的框架,而將一些步驟延遲到子類中。模板方法模式使得子類可以在不改變一個算法結構的情況下,重定義該算法的某些特定步驟。

      refresh方法中調用的12個步驟方法,為Ioc容器的創建定義了一個總體框架。在各種具體的ApplicationContext的子類中,會根據自身具體的特性,再對這12個步驟方法進行重寫,但是創建容器的總體步驟是不變的。

3.2源碼

public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
      // Prepare this context for refreshing.
      //準備刷新上下文環境:設置其啟動日期和活動標志,初始化上下文環境中的占位符屬性源
      prepareRefresh();      // Tell the subclass to refresh the internal bean factory.
      //實例化DefaultListableBeanFactory實例并返回,對BeanFactory進行定制,加載BeanDefinition的信息
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();      // Prepare the bean factory for use in this context.
      //配置beanFactory容器的特性
      prepareBeanFactory(beanFactory);      try {
         // Allows post-processing of the bean factory in context subclasses.
         //在容器初始化后,預留在子類中的上下文中,可以對容器進行修改
         postProcessBeanFactory(beanFactory);         // Invoke factory processors registered as beans in the context.
         // 執行注冊在容器中的各種BeanFactory的處理器
         invokeBeanFactoryPostProcessors(beanFactory);         // Register bean processors that intercept bean creation.
         //注冊Bean的各種處理器。處理器會在創建bean時調用。
         registerBeanPostProcessors(beanFactory);         // Initialize message source for this context.
         //初始化上下文的Message源。如:i18n國際化處理
         initMessageSource();         // Initialize event multicaster for this context.
         //為上下文初始化應用程序廣播器
         initApplicationEventMulticaster();         // Initialize other special beans in specific context subclasses.
         //在特定的上下文中,留給子類來的初始化其他的特殊bean
         onRefresh();         // Check for listener beans and register them.
         // 查看ApplicationListener類型的bean,并注冊他們。
         registerListeners();         // Instantiate all remaining (non-lazy-init) singletons.
         // 對上下文環境中剩余的單例bean完成初始化(非惰性的bean)
         finishBeanFactoryInitialization(beanFactory);         // Last step: publish corresponding event.
               // 調用LifecycleProcessor生命周期處理器的onRefresh方法并發布ContextRefreshedEvent通知,
         // 來完成上下文的刷新過程。
         finishRefresh();
      }      catch (BeansException ex) {
         if (logger.isWarnEnabled()) {
            logger.warn("Exception encountered during context initialization - " +
                  "cancelling refresh attempt: " + ex);
         }         // Destroy already created singletons to avoid dangling resources.
         //銷毀上下文容器中所有緩存的單例bean,已避免占用資源。
         destroyBeans();         // Reset 'active' flag.
         //取消此上下文的刷新嘗試,并重置active標志。
         cancelRefresh(ex);         // Propagate exception to caller.
         throw ex;
      }      finally {
         // Reset common introspection caches in Spring's core, since we
         // might not ever need metadata for singleton beans anymore...
         resetCommonCaches();
      }
   }
}
 3.2.1prepareRefresh

      prepareRefresh方法主要是對上下文的刷新做了一些準備工作,該方法中主要做了以下幾件事情。

  1. 激活開關

      prepareRefresh方法的激活開關,主要是程序中記錄了當前的時間戳,打開了當前上下文是否處于活動狀態的標志(設置為true) ,關閉當前上下文是否處于關閉狀態的標志(設置為false)。

  1. 初始化占位符

   initPropertySources方法是用于初始化上下文環境中的占位符屬性。但是在AbstractApplicationContext類中,initPropertySources方法只是一個空方法,沒有任何實現代碼。該方法是專門預留給子類擴展實現用的。

   我們可以自己實現一個繼承至AbstractApplicationContext的子類,并在子類的initPropertySources方法中,根據自己的需求來設置需要驗證的占位符。

  1. 對占位符屬性進行驗證

      Spring對占位符屬性進行驗證時,先獲取ConfigurableEnvironment類型的實例,然后再調用這個實例的validateRequiredProperties方法來進行驗證。

      在validateRequiredProperties方法中,會判斷占位符的屬性值是否為空,若值為空,就會拋出異常。默認情況下,一般是對系統中的環境變量和JVM的環境變量來進行判斷。

3.2.2obtainFreshBeanFactory

      obtainFreshBeanFactory方法從方法名上,顧名思義就是獲取BeanFactory容器。Spring經過這個函數之后,ApplicationContext就已經擁有了BeanFactory 的全部功能。obtainFreshBeanFactory方法很簡單,它主要調用了兩個方法,這兩個方法分別是refreshBeanFactory和getBeanFactory方法。

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {   //創建BeanFactory容器實例   refreshBeanFactory();   //返回創建的BeanFactory容器實例   return getBeanFactory();}

refreshBeanFactory方法

      refreshBeanFactory方法的作用主要是創建BeanFactory容器的實例。refreshBeanFactory方法在AbstractApplicationContext類中只是一個虛方法,沒有給出具體的實現。這個方法的具體實現是在子類AbstractRefreshableApplicationContext類中給出的。具體源碼如下所示:

protected final void refreshBeanFactory() throws BeansException {   //判斷是否已經創建了BeanFactory容器   //如果已經創建,則銷毀容器中的bean,并關閉容器   if (hasBeanFactory()) {      destroyBeans();      closeBeanFactory();   }   try {       //使用new方式創建一個DefaultListableBeanFactory的容器      DefaultListableBeanFactory beanFactory = createBeanFactory();      //給容器設置一個序列化的id      beanFactory.setSerializationId(getId());      //自定義DefaultListableBeanFactory容器的相關屬性      customizeBeanFactory(beanFactory);      //給容器加載BeanDefinition      loadBeanDefinitions(beanFactory);      this.beanFactory = beanFactory;   }   catch (IOException ex) {      throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);   }}

      通過以上源碼可以發現refreshBeanFactory方法主要做了以下幾件事情:

  1. 創建DefaultListableBeanFactory容器

      對于DefaultListableBeanFactory容器的創建, Spring中直接是new的方式創建了一個DefaultListableBeanFactory的實例,非常簡單。DefaultListableBeanFactory是Bean工廠的一個默認實現,它提供了容器的基本功能。

  1. 給容器指定一個序列化的id
  2. 自定義容器的相關屬性
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {   if (this.allowBeanDefinitionOverriding != null) {      beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);   }   if (this.allowCircularReferences != null) {      beanFactory.setAllowCircularReferences(this.allowCircularReferences);   }}

      customizeBeanFactory方法用于自定義容器的相關屬性。方法中判斷了allowBeanDefinitionOverriding和allowCircularReferences這兩個屬性的值是否為空,不為空的話,就對容器進行屬性值設置。

      allowBeanDefinitionOverriding屬性表示是否允許覆蓋同名的BeanDefinition,默認值是true。

      allowCircularReferences屬性表示是否允許bean之間能否進行循環依賴,默認值也是true。

  1. 給容器加載BeanDefinition

      BeanDefinition定義了描述Bean的元數據信息。BeanDefinition的加載,其實就是把Spring外部對Bean的定義信息轉化成IoC容器中內部數據結構的過程。

      IoC容器對Bean的管理和依賴注入功能的實現,其實都是通過對其持有的BeanDefinition進行各種相關操作來完成的。

      Spring外部對BeanDefinition的定義是多種形式的,BeanDefinition的定義有xml文件,properties文件和注解等形式。對于這三種形式的BeanDefinition,Spring分別提供了XmlBeanDefinitionReader,PropertiesBeanDefinitionReader,AnnotatedBeanDefinitionReader三個類來加載相應的BeanDefinition信息。

getBeanFactory方法

      getBeanFactory方法的作用主要是返回已經創建的BeanFactory容器實例,比較簡單,無需展開。

3.2.3prepareBeanFactory

      prepareBeanFactory方法主要是對beanFactory容器的特性進行一些配置的準備工作。

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {   // Tell the internal bean factory to use the context's class loader etc.   //設置容器的ClassLoader   beanFactory.setBeanClassLoader(getClassLoader());   //設置容器的SpEL語言解析器,增加對SpEL語言的支持。   beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));   //添加容器的屬性編輯器   beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));   // Configure the bean factory with context callbacks.   //為容器注冊ApplicationContextAwareProcessor的后置處理器   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.registerRe

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/716040.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/716040.shtml
英文地址,請注明出處:http://en.pswp.cn/news/716040.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

SQL 術語:Join 中的 Build 和 Probe 是什么意思?

博主歷時三年精心創作的《大數據平臺架構與原型實現:數據中臺建設實戰》一書現已由知名IT圖書品牌電子工業出版社博文視點出版發行,點擊《重磅推薦:建大數據平臺太難了!給我發個工程原型吧!》了解圖書詳情,…

如何在Vue中實現事件處理?

Vue是一種流行的JavaScript框架,廣泛應用于前端開發。在Vue中,事件處理是一個非常關鍵的概念,可以幫助我們實現用戶與頁面的交互,今天我們就來探討一下如何在Vue中實現事件處理。 首先,讓我們先了解一下在Vue中如何綁…

[pdf]《軟件方法》強化自測題業務建模需求分析共191頁,230題

潘加宇《軟件方法》強化自測題業務建模需求分析共191頁,230題,已上傳CSDN資源。 在完成書中自測題基礎上,進一步強化。 也可到以下地址下載: 資料http://www.umlchina.com/url/quizad.html 如果需要網盤提取碼:uml…

【Python】1. 背景知識

認識 Python 計算機基礎概念 什么是計算機? 很多老一輩的人, 管下面這個叫做計算機. 然鵝, 它只是 “計算器”, 和計算機是有很大區別的. 現在我們所說的計算機, 不光能進行算術運算, 還能進行邏輯判斷, 數據存儲, 網絡通信等等功能,。 以至于可以自動的完成非常復雜的工作…

代碼隨想錄day10(2)字符串:反轉字符串Ⅱ (leetcode541)

題目要求:給定一個字符串 s 和一個整數 k,從字符串開頭算起, 每計數至 2k 個字符,就反轉這 2k 個字符中的前 k 個字符。如果剩余字符少于 k 個,則將剩余字符全部反轉。如果剩余字符小于 2k 但大于或等于 k 個,則反轉前…

Spring與Spring Boot:簡化Java開發的革命性框架

Spring與Spring Boot:簡化Java開發的革命性框架 摘要:本文將深入探討Spring與Spring Boot兩個在Java開發領域具有重要地位的框架。我們將了解它們的核心概念、區別、聯系以及在實際項目中的應用。通過本文,您將更好地理解如何使用這兩個框架…

Zookeeper4:Java客戶端、應用場景以及實現、第三方客戶端curator工具包

文章目錄 Java連接Zookeeper服務端依賴代碼使用 應用場景統一命名服務統一配置管理統一集群管理服務器節點動態上下線理解實現模擬服務提供者【客戶端代碼】-注冊服務模擬服務消費者【客戶端代碼】-獲取服務信息進行請求消費 軟負載均衡分布式鎖理解實現 生產集群安裝N臺機器合…

Java中的Collection

Collection Collection 集合概述和使用 Collection集合概述 是單例集合的頂層接口,它表示一組對象,這些對象也稱為Collection的元素 JDK 不提供此接口的任何直接實現.它提供更具體的子接口(如Set和List)實現 創建Collection集合的對象 多態的方式 具體的實現類ArrayList C…

leetcode - 71. Simplify Path

Description Given a string path, which is an absolute path (starting with a slash ‘/’) to a file or directory in a Unix-style file system, convert it to the simplified canonical path. In a Unix-style file system, a period ‘.’ refers to the current di…

MATLAB環境下基于熵的聲納圖像分割算法

聲納圖像作為準確獲取水下信息的重要途徑之一,在國防、軍事、工程等方面發揮著巨大作用。然而,由于水聲信道的復雜多變和聲波本身的傳播損失,聲納圖像往往呈現出分辨率和對比度不高、噪聲干擾嚴重、目標輪廓模糊等特點。 聲納圖像的分割指的…

FCIS 2023網絡安全創新大會:洞察前沿技術,探索安全新境界(附大會核心PPT下載)

隨著信息技術的飛速發展,網絡安全問題日益凸顯,成為全球關注的焦點。作為網絡安全領域的重要盛會,FCIS 2023網絡安全創新大會如期而至,匯聚了全球網絡安全領域的頂尖專家、學者、企業家和政策制定者,共同探討網絡安全的…

備戰藍橋杯————差分數組1

引言 一、差分數組 什么是差分數組 差分數組的作用 Java代碼實現差分數組 二、 區間加法 題目描述 代碼與解題思路 總結 引言 在數字世界的海洋中,數據是構建和優化算法的基石。然而,當我們面對需要頻繁進行區間操作的數組時,傳統的逐元素…

ABAP - SALV教程10 添加可編輯checkbox列

幾乎所有的功能報表都會有那么一個選擇列,問了業務顧問,業務顧問說是用戶不習慣使用報表原生的選擇模式。效果圖SALV的選擇列是通過將列設置成checkbox_hotspot樣式,注冊單擊事件完成勾選功能的。完成步驟 將SEL列設置成checkbox_hotspot樣式…

【筆記】OpenHarmony和HarmonyOS區別及應用開發簡介

一、概念 OpenHarmony(OH) : OpenAtom OpenHarmonyHarmonyOS(HO):開發 | 華為開發者聯盟 (huawei.com) HO當前最高是3.1,在華為mate 60上面也是。關于4.0、5.0和next這類版本說法都是面向用戶的,不是開發人員。對于程序員&#…

Springboot 項目讀取yaml的配置文件信息給靜態方法使用,以及通過配置 ResourceBundle 類讀取config.properties

讀取yaml 的配置文件 配置文件信息 iot_saas_tenement:user_id: 7........8d9bprivate_key: MII.......qQbj_url: http://4.....5:8088project_name: iot_s.......rojectdevice_name: te.....ice 創建一個類 ProxyProperties 讀取配置文件信息,并對外提供get方法 …

內存的檢測與排查

內存🐎的檢測與排查 文章目錄 內存🐎的檢測與排查查殺Java Web filter型內存馬0x01 內存馬簡歷史0x02 查殺思路0x03 內存馬的識別0x04 內存馬的查殺 查殺Java Web filter型內存馬 0x01 內存馬簡歷史 其實內存馬由來已久,早在17年n1nty師傅的…

QT6 libModbus 用于ModbusTcp客戶端讀寫服務端

雖然在以前的文章中多次描述過,那么本文使用開源庫libModbus,可得到更好的性能,也可移植到各種平臺。 性能:讀1次和寫1次約各用時2ms。 分別創建了讀和寫各1個連接指針,用于讀100個寄存器和寫100個寄存器,讀寫分離。 客戶端&am…

物聯網與智慧城市:科技驅動下的城市智能化升級之路

一、引言 隨著科技的不斷進步和城市化進程的加速,物聯網與智慧城市的結合已經成為推動城市智能化升級的關鍵力量。物聯網技術以其強大的連接和數據處理能力,為智慧城市的建設提供了無限可能。本文旨在探討物聯網如何助力智慧城市的構建,以及…

SLAM ORB-SLAM2(21)基礎矩陣的計算和評分

SLAM ORB-SLAM2(21)基礎矩陣的計算和評分 1. 前言2. 基礎矩陣2.1. 對級約束2.2. 推導2.3. 計算原理 3. ComputeF214. CheckFundamental 1. 前言 在 《SLAM ORB-SLAM2(20)查找基礎矩陣》 中了解到 查找基礎矩陣主要過程&#xff1…

web基礎03-JavaScript

目錄 一、JavaScript基礎 1.變量 2.輸出 3.變量提升 4.區塊 5.JavaScript數據類型 6.查看數值類型 7.undefined和null 8.布爾值 9.和的區別 10.算數/三元/比較/邏輯/賦值運算符 11.特殊字符 12.字符串 (1)獲取字符串長度 (2&am…