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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈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盘的…