Spring IOC容器在Web環境中是如何啟動的(源碼級剖析)?

文章目錄

    • 一、Web 環境中的 Spring MVC 框架
    • 二、Web 應用部署描述配置
      • 傳統配置(web.xml):
      • Java配置類(Servlet 3.0+):
    • 三、核心啟動流程詳解
      • 1. 啟動流程圖
      • 2. ★容器初始化入口:ContextLoaderListener
      • 3. ★容器創建核心:ContextLoader
    • 四、擴展:Web容器中的上下文設計
      • WebApplicationContext
        • 核心功能點:
        • 源碼解析
      • XmlWebApplicationContext
        • 源碼解析
    • 五、總結與最佳實踐

在Java Web 應用開發中,Spring的IOC容器同樣扮演著核心角色。Spring IOC(控制反轉)容器的啟動過程需要與 Web 容器【Servlet容器】(如 Tomcat、Jetty)的生命周期集成。本文將深入剖析這一過程的核心機制。

一、Web 環境中的 Spring MVC 框架

在Web環境中,業內主流的是Spring MVC框架, 但它是建立在Spring IoC容器基礎上的。所以想要深入了解Spring MVC框架,首先要了解 Spring IoC 容器是如何在 Web 環境中被載入并生效的

  • Spring IoC是Spring框架的基石,是一個獨立的模塊,它并不能直接在 Web 容器中發揮作用;要在Web環境中使用IoC容器,則需要 Spring 為它設計一個啟動過程,好引導它在web環境中啟動。

  • 具體說來,這個啟動過程是和 Web 容器【Servlet容器】(如 Tomcat、Jetty)的生命周期的啟動過程集成在一起的。在這個過程中,一方面處理 Web 容器的啟動,另一方面通過設計特定的Web容器過濾器,將IoC容器載人到Web環境中并將其初始化

  • 等啟動過程執行完成后Spring IoC容器就能正常工作;而Spring MVC是建立在IoC容器的基礎上的,這樣才能建立起完整MVC框架的運行機制,從而可以接收、響應從Web容器傳遞的HTTP請求。

下面就以 TomcatWeb 容器的進行分析這個啟動過程

二、Web 應用部署描述配置

在 Tomcat 中,web.xml 是應用的部署配置文件。在Spring MVC項目中的 web.xml 中經常能看到與 Spring 相關的部署配置。

傳統配置(web.xml):

<!-- DispatcherServlet配置 -->
<servlet><servlet-name>app</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>/WEB-INF/app-context.xml</param-value></init-param><load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping><servlet-name>app</servlet-name><url-pattern>/*</url-pattern>
</servlet-mapping><context-param><param-name>contextConfigLocation</param-name><param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<!-- 根容器初始化 -->
<listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

要點解析:
web.xml 這個部署描述文件中,定義了一些對象:

  • DispatcherServlet:是 Spring MVC 的 DispatcherServlet,且是一個Servlet對象。起著分發請求的作用,是MVC框架中很重要的一個類。
  • servlet > init-param:用來指定 Spring MVC 容器讀取Web Bean定義的XML文件路徑,這里配置文件指定為/WEB-INF/app-context.xml
  • servlet-mapping:為這個 DispatcherServlet 定義了對應的URL映射,以指定這個Servlet需要處理的HTTP請求范圍。
  • context-param 參數用來指定 Spring IoC 容器讀取Bean定義的XML文件路徑,在這里,這個配置文件被定義為 WEB-INF/applicationContext.xml
  • ContextLoaderListener核心類,是 Spring MVC 的啟動類,被定義為一個監聽器,它是與Web服務器的生命周期相關聯的,是它負責完成 IoC 容器在 Web 環境中的啟動工作

核心機制

  1. 關鍵組件:通過DispatchServlet(請求轉發器)和ContextLoaderListener(容器初始化監聽器)實現與Web容器的對接。
  2. 耦合機制:基于ServletContext實現與Web容器的解耦,ServletContext作為servlet規范的體現,既是容器與應用的橋梁,又為Spring IoC容器提供宿主環境。
  3. 容器體系構建ContextLoaderListener負責初始化建立IoC容器體系,隨后初始化DispatchServlet作為請求處理器。
  4. 完整流程:這兩個組件協同工作,使基于IoC容器的Spring MVC能夠完成HTTP請求的接收、處理和響應。

下面是 Servlet 3.0+ 規范后我們可以直接使用Java配置類的方式實現web.xml相同功能;

Java配置類(Servlet 3.0+):

public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {@Overrideprotected Class<?>[] getRootConfigClasses() {return new Class[]{RootConfig.class}; }@Overrideprotected Class<?>[] getServletConfigClasses() {return new Class[]{WebConfig.class};  }@Overrideprotected String[] getServletMappings() {return new String[]{"/"};}
}

下面我們看一下IoC容器在Web環境中的啟動及代碼實現。

三、核心啟動流程詳解

1. 啟動流程圖

在這里插入圖片描述

2. ★容器初始化入口:ContextLoaderListener

初始化入口類ContextLoaderListener,源碼位置:org.springframework.web.context.ContextLoaderListener

在這里插入圖片描述
核心要點

  • 可以看到它實現了 ServletContextListener 接口,這個接口是 Servlet API 中定義的,提供了與 Servlet 生命周期相結合的回調;它是在Web容器中配置的監聽器,作為監聽器當監聽到Web服務器(Tomcat)啟動時,它的 contextInitialized()方法會被調用從而在這觸發載入 IoC 容器
  • 另外,它還繼承了 ContextLoader,具體的載入 IoC 容器的過程是由 ContextLoader 來完成的。

3. ★容器創建核心:ContextLoader

創建核心類ContextLoader,源碼位置:org.springframework.web.context.ContextLoader

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

核心要點

  1. 創建Web根上下文容器實例:
    • 創建在 ServletContext 中存儲的Web根上下文容器(Spring IOC容器);會根據ServletContext中獲取contextClass參數的配置來創建指定的IoC容器,默認使用XmlWebApplicationContext作為在Web環境中使用的IoC容器。
    • 直接通過反射實例化需要的IoC容器
  2. 載入根上下文的雙親上下文:
    • 判斷當前Web根上下文的Parent contextnull時為當前 Web 應用的根上下文設置一個父上下文,從而支持上下文的繼承和共享,適用于需要分層或共享資源的復雜應用場景。
  3. 核心初始化方法(配置并刷新容器):
    • 為當前Web應用容器配置容器Web環境
    • 加載配置文件(從web.xmlcontextConfigLocation參數);
    • ServletContextServletConfig 中的屬性添加到容器環境中,以便在后續的應用上下文初始化過程中使用;
    • 擴展點,可對 ConfigurableWebApplicationContext 進行自定義配置,在上下文刷新(refresh())之前被調用;
    • IoC容器的初始化(調用AbstractApplicationContext.refresh()

四、擴展:Web容器中的上下文設計

Spring框架為Web應用提供了專用的上下文(IOC容器)的擴展接口類 WebApplicationContext 來滿足Web環境中啟動過程的需要,其主要繼承關系如下:

在這里插入圖片描述

WebApplicationContext

核心功能點:

WebApplicationContext 作為 Spring 框架中一個核心接口,主要用于為 Web 應用程序提供配置。它擴展了 ApplicationContext 接口,增加了與 Web 環境相關的功能。以下是其主要作用:

  1. 提供Web容器 ServletContext 的訪問
    允許訪問標準的 Servlet APIServletContext 對象,用于與底層 Web 容器交互。
  2. 支持 Web 特定的作用域
    定義了 Web 特定的作用域標識符,例如:
    • SCOPE_REQUEST:請求作用域。
    • SCOPE_SESSION:會話作用域。
    • SCOPE_APPLICATION:全局 Web 應用作用域。
  3. 與 Web 環境相關的 Bean 定義
    提供了與 ServletContext 和初始化參數相關的 Bean 名稱,例如:
    • SERVLET_CONTEXT_BEAN_NAMEServletContext 的 Bean 名稱。
    • CONTEXT_PARAMETERS_BEAN_NAMEServletContext 初始化參數的 Bean 名稱。
    • CONTEXT_ATTRIBUTES_BEAN_NAMEServletContext 屬性的 Bean 名稱。
  4. 支持層次化上下文
    Web 應用程序上下文是分層的,整個應用程序有一個根上下文,每個 Servlet(如 Spring MVC 的 DispatcherServlet)有自己的子上下文。
  5. ServletContextAware 的集成
    自動檢測實現了 ServletContextAware 接口的 Bean,并調用其 setServletContext 方法。
源碼解析

在這里插入圖片描述

XmlWebApplicationContext

從前面類繼承關系圖中,可以看到前面了解到的默認Web容器實現XmlWebApplicationContext,它繼承自實現了擴展接口類 WebApplicationContext的類 。在 ApplicationContext 的基礎上,增加了對 Web 環境 和 XML 配置定義 的處理。

XmlWebApplicationContext 的初始化過程中,Web容器(Servlet容器)中的IoC容器隨之被建立起來,具體過程則是從 refresh() 方法入口的, 這里不做過多解析。

下面主要針對XmlWebApplicationContext源碼了解學習下。

源碼解析

在這里插入圖片描述

從上面的源代碼中可以看到,在 XmlWebApplicationContext 中并沒有多少功能點,主要處理了如何在Web環境中獲取BeanDefinition信息,這是因為其繼承的父類已經具備基礎上下文功能(IOC容器的能力)。
總結一下就是:

  • ?繼承體系基礎
    • 通過繼承AbstractRefreshableConfigApplicationContext等父類已具備基礎上下文功能
    • 核心挑戰轉為Web環境下BeanDefinition資源的定位與加載
  • 資源獲取機制
    • 解析web.xml中配置的contextConfigLocation參數確定配置文件路徑
    • 將ServletContext路徑轉換為Spring可識別的Resource對象
  • 定義加載流程
    • 使用XmlBeanDefinitionReader讀取XML配置并解析BeanDefinition
    • 加載過程與XmlFileSystemBeanFactory類似,但需適配Web資源路徑格式
  • 初始化完成
    • 通過refresh()方法觸發完整的容器初始化生命周期
    • 最終形成包含所有BeanDefinition的可運行上下文環境

該上下文(IOC容器)的設計完美的實現了Web環境與標準IoC容器初始化流程的無縫銜接。

五、總結與最佳實踐

通過源碼分析,我們揭示以下關鍵機制:

  1. Web上下文容器啟動:由ContextLoaderListener監聽Web容器(Tomcat)的啟動來創建初始化web應用的根上下文(父IOC容器)
  2. Web上下文容器刷新refresh()方法是容器初始化的核心入口,繼承自父類的功能實現,包含12個關鍵步驟(BeanFactory創建、后處理器注冊、單例初始化等)
  3. Web上下文父子容器交互:子容器通過setParent()方法引用父容器;Bean查找時通過getParentBeanFactory()實現委托

深入理解這些底層機制,將幫助開發者更好地診斷啟動問題、優化應用性能,并為復雜場景(如動態注冊Bean)提供解決方案。


ContextLoaderListener Diagram
在這里插入圖片描述


End!

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

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

相關文章

18個優質Qt開源項目匯總

1&#xff0c;Clementine Music Player Clementine Music Player 是一個功能完善、跨平臺的開源音樂播放器&#xff0c;非常適合用于學習如何開發媒體類應用&#xff0c;尤其是跨平臺桌面應用。它基于 Qt 框架開發&#xff0c;支持多種操作系統&#xff0c;包括 Windows、macO…

計算機視覺:AI 的 “眼睛” 如何看懂世界?

1. 什么是計算機視覺&#xff1a;讓機器 “看見” 并 “理解” 的技術1.1 計算機視覺的核心目標計算機視覺&#xff08;CV&#xff09;是人工智能的一個重要分支&#xff0c;它讓計算機能夠 “看懂” 圖像和視頻 —— 不僅能捕捉像素信息&#xff0c;還能分析內容、提取語義&am…

華為OD刷題記錄

華為OD刷題記錄 刷過的題 入門 1、進制 2、NC61 doing 訂閱專欄

QT學習教程(二十五)

雙緩沖技術&#xff08;Double Buffering&#xff09;&#xff08; 2、公有函數實現&#xff09;#include <QtGui> #include <cmath> using namespace std; #include "plotter.h"以上代碼為文件的開頭&#xff0c;在這里把std 的名空間加入到當前的全…

設計模式筆記_結構型_裝飾器模式

1.裝飾器模式介紹裝飾器模式是一種結構型設計模式&#xff0c;允許你動態地給對象添加行為&#xff0c;而無需修改其代碼。它的核心思想是將對象放入一個“包裝器”中&#xff0c;這個包裝器提供了額外的功能&#xff0c;同時保持原有對象的接口不變。想象一下&#xff0c;你有…

day25 力扣90.子集II 力扣46.全排列 力扣47.全排列 II

子集II給你一個整數數組 nums &#xff0c;找出并返回所有該數組中不同的遞增子序列&#xff0c;遞增子序列中 至少有兩個元素 。你可以按 任意順序 返回答案。數組中可能含有重復元素&#xff0c;如出現兩個整數相等&#xff0c;也可以視作遞增序列的一種特殊情況。示例 1&…

Solidity 中的`bytes`

在 Solidity 中&#xff0c;bytes 和 bytes32 都是用來保存二進制數據的類型&#xff0c;但它們的長度、使用場景、Gas 成本完全不同。? 一句話區分類型一句話總結bytes32定長 32 字節&#xff0c;適合做哈希、地址、標識符等固定長度數據。bytes動態長度字節數組&#xff0c;…

初學者STM32—PWM驅動電機與舵機

一、簡介 上一節課主要學習了輸出比較和PWM的基本原理和結構&#xff0c;本節課就主要以實踐為主通過STM32最小系統板和驅動器控制舵機和直流電機。 上一節課的坐標 初學者STM32—輸出比較與PWM-CSDN博客 二、舵機 舵機是一種根據輸入PWM信號占空比來控制輸出角度的裝置 輸…

C++中的異常處理機制:try-catch

一、基本概念 異常&#xff08;Exception&#xff09;&#xff1a;程序執行過程中發生的非正常情況&#xff0c;比如除以零、訪問越界、內存不足等。 異常處理&#xff08;Exception Handling&#xff09;&#xff1a;對異常情況進行捕獲、分析&#xff0c;并采取補救措施&…

如何從 Windows 11 或 10 遠程訪問 Ubuntu 24.04 或 22.04 桌面

了解如何使用 RDP(遠程桌面協議)從 Windows 11 或 10 遠程連接 Ubuntu 24.04 Noble 或 22.04 LTS Jammy JellyFish 桌面的步驟。 Windows 提供了一個便捷的功能,稱為遠程桌面連接,它使用 RDP 協議來遠程連接 PC。當從 Windows 系統建立遠程桌面連接時,使用起來非常簡單,…

Linux 服務器中,Tab 鍵自動補全功能失效

在 Linux 服務器中&#xff0c;Tab 鍵自動補全功能失效通常與 bash-completion 組件缺失或配置異常有關。以下是解決問題的兩個關鍵 YUM 指令及操作步驟&#xff1a;1. 安裝 bash-completion 組件 sudo yum install -y bash-completion說明&#xff1a; bash-completion 是提供…

SpringBoot服裝推薦系統實戰

Spring Boot 服裝推薦系統實例 以下是基于Spring Boot實現的服裝推薦系統的30個實例代碼示例,涵蓋核心功能和實現方法。 用戶注冊與登錄功能 @RestController @RequestMapping("/api/auth") public class AuthController {@Autowiredprivate UserService userSer…

WIN10系統優化篇(一)

你是否疑惑為什么別人家的電腦運行速度飛快&#xff0c;而自己的卻卡頓難用&#xff1f;其實&#xff0c;很多時候 Windows 系統可以通過簡單的優化措施來提升使用體驗。本文根據項目實戰多年對 Win10 優化經驗&#xff0c;將幫你找出系統卡頓的原因&#xff0c;并給出針對性的…

Flutter狀態管理篇之ChangeNotifier基礎篇(一)

目錄 前言 一、什么是ChangeNotifier 二、ChangeNotifier 的基本用法 三、結合Flutter UI 使用 四、結合 Provider 的高級用法 五、ChangeNotifier 的優勢與注意事項 5.1 優勢 5.2 注意事項 六、與 ValueNotifier 的比較 七、實際應用場景 八、總結 前言 在 Flutter…

react17更新哪些新特性

React 17 是一個“無新特性”的發布版本&#xff0c;它的主要目標是為未來的 React 版本打好基礎&#xff0c;同時改善與舊版本共存和升級的體驗。雖然沒有引入新的開發者 API&#xff0c;但它在內部做了很多重要的改進。以下是 React 17 的核心更新內容和特性&#xff1a;&…

Unity 常見數據結構分析與實戰展示 C#

Unity 常見數據結構分析與實戰展示 提示&#xff1a;內容純個人編寫&#xff0c;歡迎評論點贊&#xff0c;來指正我。 文章目錄Unity 常見數據結構分析與實戰展示1. 引言2. Unity 數據結構概述3. 常見數據結構1. 數組&#xff08;Array&#xff09;2. 列表&#xff08;List&…

【Linux網絡編程】應用層協議 - HTTP

目錄 初識HTTP協議 認識URL HTTP協議的宏觀格式 Socket封裝 TcpServer HttpServer 整體設計 接收請求 web根目錄與默認首頁 發送應答 完善頁面 HTTP常見Header HTTP狀態碼 HTTP請求方法 cookie與session Connection 抓包 初識HTTP協議 應用層協議一定是基于…

技術演進中的開發沉思-36 MFC系列: 對話框

MFC這個章節里&#xff0c;不能忽視的是對話框的開發。如果把 MFC 程序比作一棟辦公樓&#xff0c;那對話框就是「會客室」—— 它是程序與用戶面對面交流的地方&#xff1a;用戶在這里輸入數據&#xff0c;程序在這里展示信息&#xff0c;彼此的互動都從這個空間開始。今天圍繞…

(李宏毅)deep learning(五)--learning rate

一&#xff0c;關于learning rate的討論&#xff1a;&#xff08;1&#xff09;在梯度下降的過程中&#xff0c;當我們發現loss的值很小的時候&#xff0c;這時我們可能以為gradident已經到了local min0&#xff08;低谷&#xff09;,但是很多時候&#xff0c;loss很小并不是因…

pytorch:tensorboard和transforms學習

tensorboard:可視化數據 在anaconda安裝&#xff1a; pip install tensorboard2.12.0最好使用這個版本 不然后面調用會報錯 因為版本過高的原因 然后還碰到了安裝的時候 安裝到C盤去了 但是我用的虛擬環境是在E盤&#xff1a;此時去C盤把那些新安裝的復制過來就好了 附錄我C盤的…