Spring MVC 中web容器和IOC容器启动过程

SpringMVC启动流程——IOC容器创建 SpringMVC启动流程——IOC容器创建 1. 简介 Spring容器是管理service和dao的。 SpringMVC容器是管理controller对象的。 Spring容器和SpringMVC容器的关系是父子容器的关系。Spring容器是父容器,SpringMVC容器是子容器。在子容器里可以访问父容器里的对象,但是在父容器里不可以访问子容器的对象,说的通俗点就是,在controller... 阅读详情

【本文是为了梳理知识的总结性文章,总结了一些自认为相关的重要知识点,只为巩固记忆以及技术交流,忘批评指正。其中参考了很多前辈的文章,包括图片也是引用,如有冒犯,侵删。】

1 概念

web容器:可以部署多个WEB应用程序的环境,例如Tomcat、weblogic、JBoss等。

IOC容器:Inversion of Control 容器,是Spring的两大基本功能之一(还有AOP),用来管理bean以及其依赖关系。

容器上下文:所谓上下文,它是用来存储系统的一些初始化信息。例如web容器上下文ServletContext,是一个全局的储存信息的空间。服务器启动,其就存在,服务器关闭,其才释放。所有用户共用一个ServletContext。所以,为了节省空间,提高效率,ServletContext中,要放必须的、重要的、所有用户需要共享的线程又是安全的一些信息。

在Web环境中,我们的程序要部署到web容器上才能工作,而我们的程序如果使用了Spring来进行bean及其依赖关系管理,则必须使用IOC容器。Spring IoC是一个独立的模块,它并不是直接在Web容器中发挥作用的,那么Spring loC容器是如何在Web环境中被载入并起作用的呢?

如果要在Web环境中使用loC容器,需要Spring为loC设计一个启动过程,把IoC容器导入,并在Web容器中建立起来。具体说来,这个启动过程是和Web容器的启动过程集成在一起的。在这个过程中,一方面处理Web容器的启动,另一方面通过设计特定的Web容器拦截器,将IoC容器载入到Web环境中来,并将其初始化。在这个过程建立完成以后,IoC容器才能正常工作,而Spring MVC是建立在loC容器的基础上的,这样才能建立起MVC框架的运行机制,从而响应从Web容器传递的HTTP请求。

2 ContextLoaderListener

在web.xml中配置Spring时我们经常会使用以下部署描述:

<listener>
    <listener-class>
        org.springframework.web.context.ContextLoaderListener
    </listener-class>
</listener>

ContextLoaderListener是Spring提供的类,是为在Web容器中建立loC容器服务的。ContextLoaderListener 是一个监听器,这个监听器是与Web容器的生命周期相关联的,由ContextLoaderListener监听器负责完成loC容器在Web环境中的启动工作。loC容器的启动过程就是建立上下文的过程,该上下文是与ServletContext相伴而生的。

在ContextLoaderListener中,实现了ServletContextListener接口,这个接口是在ServletAPI中定义的,这个接口里的函数会结合Web容器的生命周期被调用。因为ServletContextListener是ServletContext的监听者,如果ServletContext发生变化,会触发出相应的事件,而监听器一直在对这些事件进行监听,如果接收到了监听的事件,就会做出预先设计好的响应动作。由于ServletContext的变化而触发的监听器的响应具体包括:在服务器启动时,ServletContext被创建的时候;服务器关闭时,ServletContext将被销毁的时候等。
对应这些事件及Web容器状态的变化,在监听器中定义了对应的事件响应的回调方法。比如在服务器启动时,ServletContextListener 的contextlnitialized()方法被调用,服务器将要关闭时,ServletContextListener的 contextDestroyed()方法被调用。这样我们就可以跟随这web容器的启动而创建IOC容器,关闭时销毁IOC容器,实现Web容器和IOC容器的共同启动。

了解了Web容器中监听器的工作原理,下面看看服务器启动时ContextLoaderListener的调用完成了什么。在这个初始化回调中,创建了ContextLoader,同时会利用创建出来的ContextLoader来完成IoC容器的初始化。而ContextLoader本身就是ContextLoaderListener的基类,所以可以直接赋值this。

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class ContextLoaderListener extends ContextLoader implements ServletContextListener {

	private ContextLoader contextLoader;

	public ContextLoaderListener() {
	}

	public ContextLoaderListener(WebApplicationContext context) {
		super(context);
	}

	/**
	 * Initialize the root web application context.
	 */
	public void contextInitialized(ServletContextEvent event) {
		this.contextLoader = createContextLoader();
		if (this.contextLoader == null) {
			this.contextLoader = this;
		}
		this.contextLoader.initWebApplicationContext(event.getServletContext());
	}

	/**
	 * Create the ContextLoader to use. Can be overridden in subclasses.
	 */
	@Deprecated
	protected ContextLoader createContextLoader() {
		return null;
	}

	/**
	 * Return the ContextLoader used by this listener.
	 */
	@Deprecated
	public ContextLoader getContextLoader() {
		return this.contextLoader;
	}


	/**
	 * Close the root web application context.
	 */
	public void contextDestroyed(ServletContextEvent event) {
		if (this.contextLoader != null) {
			this.contextLoader.closeWebApplicationContext(event.getServletContext());
		}
		ContextCleanupListener.cleanupAttributes(event.getServletContext());
	}

}

3 ContextLoader

具体的载入IoC容器的过程是由ContextLoaderListener交由ContextLoader来完成的。在这个初始化过程中,需要完成根上下文在Web容器中的创建。这个根上下文是作为Web容器中唯一的实例而存在的,如果初始化过程中,发现根上下文已经被创建了,则会抛出异常提示创建失败。根上下文创建成功以后,会被存到Web容器的ServletContext中去,供需要时使用。存取这个根上下文的路径是由Spring预先设置好的,在ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE的属性中定义这个路径,这个路径默认被设置为:

ROOT_WEB_APPLICATTON_CONTEXT_ATTRIBUTE=WebApplicationContext.class.getName()+".RooT"

 

	public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
	// 判断根上下文是否存在 
		if(servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
			throw new IllegalStateException(
			"Cannot initialize context because there is already a root application context present - " +
			"check whether you have multiple ContextLoader* definitions in your web.xml!");
		 }
		long startTime = System.currentTimeMillis();

		try {
			// 创建WebApplicationContext
			if (this.context == null) {
				this.context = createWebApplicationContext(servletContext);
			}
			if (this.context instanceof ConfigurableWebApplicationContext) {
				ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
				if (!cwac.isActive()) {
					if (cwac.getParent() == null) {
						ApplicationContext parent = loadParentContext(servletContext);
						cwac.setParent(parent);
					}
					configureAndRefreshWebApplicationContext(cwac, servletContext);
				}
			}
		// 保存上下文到servletContext			 
		servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
			ClassLoader ccl = Thread.currentThread().getContextClassLoader();
			if (ccl == ContextLoader.class.getClassLoader()) {
				currentContext = this.context;
			}
			else if (ccl != null) {
				currentContextPerThread.put(ccl, this.context);
			}

			return this.context;
		}
		catch (RuntimeException ex) {
			throw ex;
		}
		catch (Error err) {
			throw err;
		}
	}

具体的根上下文的创建如下代码所示,使用什么样的类作为上下文是在determineContextClass方法中确定的。

protected WebApplicationContext createWebApplicationContext(ServletContext sc) {
		Class<?> contextClass = determineContextClass(sc);
		if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
			throw new ApplicationContextException("Custom context class [" + contextClass.getName() +
					"] is not of type [" + ConfigurableWebApplicationContext.class.getName() + "]");
		}
		return (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
	}

在确定使用何种IoC容器的过程中可以看到,应用可以在部署描述符中指定使用什么样的IoC容器,这个指定操作是通过CONTEXT_CLASS_PARAM参数的设置完成的。如果没有指定特定的loC容器,将使用默认的IoC容器,也就是XmlWebApplicationContext对象作为在Web环境中使用的IoC容器。

protected Class<?> determineContextClass(ServletContext servletContext) {
		String contextClassName = servletContext.getInitParameter(CONTEXT_CLASS_PARAM);
		if (contextClassName != null) {
			try {
				return ClassUtils.forName(contextClassName, ClassUtils.getDefaultClassLoader());
			}
			catch (ClassNotFoundException ex) {
				throw new ApplicationContextException(
						"Failed to load custom context class [" + contextClassName + "]", ex);
			}
		}
		else {
			contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());
			try {
				return ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader());
			}
			catch (ClassNotFoundException ex) {
				throw new ApplicationContextException(
						"Failed to load default context class [" + contextClassName + "]", ex);
			}
		}
	}

4 配置自定义IOC容器

如果需要使用自定义的IOC容器类,可以再Web.xml中进行如下配置:

<context-param>
    <param-name>contextClass</param-name>
	<param-value>
		com.bussiness.framework.springexp.CustomizeXmlApplicationContext
	</param-value>
</context-param>

那么spring启动的时候就会使用自定义类进行IOC容器初始化了。

5 参考

  1. 《Spring技术内幕》
  2. Spring framework 3.2.6
【β-Boltzmann探索策略】 𝜀是一个介于0和1之间的参数,用于控制探索和利用的比例。当𝜀较大时,智能体更倾向于探索;当𝜀较小时,智能体更倾向于利用已知信息。 阅读详情

相关推荐

STM32 超声波模块输入捕获测距(标准库)

通道2设置为下降沿触发,触发瞬间会将CNT的记录到CCR2中,由于上升沿触发时已经将CNT置零所以此时的CNT的值就是高电平的持续时间。通道1设置为上升沿触发,触发的瞬间会将CNT的值记录到CCR1里面,同时设置通道1触发带有从模式,并把从模式设置为置零CNT。超声波传感器模块上面通常有两个超声波元器件,一个用于发射,一个用于接收。电路板上有四个引脚:VCC、GND、Trig(触发)、Echo(回应)。输入捕获原理可以看看这位大佬,感觉写的很清楚,工作电压与电流:5V,15mA。感测角度:不小于15度。

qq_62425900的博客 2082

项目里面哪些地方用到了ioc_Spring从入门到入土——IOC概述及推导

前面第一篇我们认识了什么是Spring以及通过官网的指引,编写并启动了第一个属于我们的Spring程序,虽然程序启动了,但是对于里面的内容以及如何实现的我们还是不是十分的清楚,那么接下来我们就首先先来了解一下Spring中的一个核心概念——IOCIoC(控制翻转)推导之前的代码架构通常我们以前实现项目的时候会分为这么几步:先写一个UserDao接口public interface UserDao ...

weixin_39616339的博客 446

Disk Drill 使用教程

Disk Drill只需单击几下,即可恢复USB闪存驱动器上已删除的数据,包括丢失的照片,文档和其他文件类型。Disk Drill是真正的多合一应用程序,可在Mac上恢复闪存驱动器。Disk Drill将自动应用最佳的笔式驱动器恢复算法来恢复Mac数据。 USB闪存驱动器是一种传输和存储信息的好方法,但是如果错误地丢失或删除了存储在其中的文件,会发生什么呢?当您需要Mac的闪存驱动器数据恢复软件时,Disk Drill是您的最佳选择。Disk Drill将扫描您的USB闪存驱动器(也称为笔式驱动器)并查找

zjj778899的博客 1万+

Spring之IOC

安全技术方面:Shiro springSecurity数据库层面:hibernate/mybatis SpringDataJpa消息中间件:activityMQ、RabbitMQ、kaffka spring..MQSpring是一个开源框架,它由Rod Johnson创建。它是为了解决企业应用开发的复杂性而创建的。3.1 id:在容器中查找Bean的id(唯一、且不能以/开头)3.2 class:bean的完整类名。...

m0_67864917的博客 294

开源AI数字人DUIX:从零构建你的智能交互助手

本文详细介绍了如何利用开源AI数字人DUIX从零构建智能交互助手。文章阐述了DUIX作为开源项目的核心优势,包括低成本启动、低网络依赖和高度可定制性,并提供了从开发环境搭建、核心模块(AI模型、语音、形象)配置到个性化业务逻辑开发与最终部署的完整实践指南,帮助开发者快速掌握构建专属AI数字人的全流程。

weixin_29051811的博客 504

自研半导体Fab缺陷分析系统:从Klarf解析到Defect Map可视化的实战替代方案

本文分享了自研半导体Fab缺陷分析系统的实战经验,重点解析了Klarf文件格式与坐标系转换的核心技术,并详细介绍了从数据解析到Defect Map可视化的完整实现路径。该系统旨在为成本敏感或追求技术自主的团队提供一套功能完备的Klarity Defect平替方案,有效降低对昂贵商业软件的依赖,实现缺陷数据的自主分析与可视化。

y7z8a的博客 707

JavaWeb

javaWeb 1.基本概念 1.1 web开发: web:网页的意思 静态web 数据不会发生变化 动态web 数据会发生变化,每个人看到的都不一样 技术栈:Servlet/JSP,ASP,PHP 在java中,动态web资源开发的技术统称为javaWeb 1.2.Web应用程序 web应用程序:可以提供浏览器访问的程序 web资源可以被外界访问,为外界提供服务 可以被访问到的资源或页面,都存在于计算机上 统一的web资源会被放在同一个文件夹上,web应用程序–>Tomc

Tzeao 570

紫光同创PGL50H开发板实战:盘古50KH视频板的多媒体处理与高速通信方案

本文详细介绍了基于紫光同创PGL50H FPGA芯片的盘古50KH视频开发板在多媒体处理与高速通信方面的实战应用。文章从开发板硬件架构解析入手,逐步指导开发环境搭建、DDR3内存控制器配置、HDMI视频输入输出实战,并重点探讨了利用板载HSST高速收发器实现光纤通信与万兆以太网的方案。最后,通过构建一个集多路视频采集、处理与光纤传输于一体的系统案例,展示了该开发板在高性能实时数据处理领域的强大潜力。

b9c0d的博客 485

Tomcat运维

tomcat从安装到项目部署

pdp1196431288的博客 2468

MATLAB对pcap文件抓包的读取

应用范围 常用的雷达信号,无线网通信信号的格式大多为pcap、wj文件,这里记录一下MATLAB读取pcap文件的方法,具体处理过程及读取协议针对不同的雷达有不同的处理方式,在这里不做说明。 程序 clc;clear;close all; %% 文件位置 filename= 'E:\File\JOB\JOB_1\data.pcap'; fid = fopen(filename,'r'); % 打开包 tmpPack = fread(fid,1350); % 只读前1350个数 读到

诗酒趁年华的博客 3579

Qt数据导出实战:从SQLite到CSV的完整流程(附内存优化技巧)

本文详细介绍了在Qt框架下,将SQLite数据库中的数据高效导出为CSV格式的完整流程。针对大数据量场景,重点分享了分块读取、流式写入等内存优化技巧,有效解决了嵌入式或资源受限环境中导出功能的内存占用与性能瓶颈问题,并提供了健壮的代码实现方案。

weixin_29313547的博客 341

windows服务的停止和开启

/// <summary> /// WindowsServiceManage /// </summary> public class WindowsServiceManage { /// <summary> /// 重启服务 /// </summary> /// &...

weixin_30600197的博客 413

YOLO26改进策略【YOLO和Mamba】| 替换骨干 Mamba-YOLO26-T !!! 最新的发文热点

模块是模型中的一个重要组成部分,其主要作用是在模型的初始阶段对输入图像进行处理,方便后续的特征提取和目标检测。以下是对。

Limiiiing的博客 900

深入分析Spring 与 Spring MVC容器启动

要想很好理解这三个上下文的关系,需要先熟悉Spring是怎样在web容器中启动起来的。Spring的启动过程其实就是其IOC容器的启动过程,对于web程序,IOC容器启动过程即是建立上下文的过程。 Spring的启动过程: 首先,对于一个web应用,其部署在web容器中,web容器提供其一个全局的上下文环境,这个上下文就是ServletContext,其为后面的spring IoC容器

XXX 1663

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

(八)Spring MVC的上下文在Web容器中的启动

Web环境下的MVC Spring IoC是一个独立的模块,并不能直接在Web容器中发挥作用。 所以要在Web容器中使用IoC容器,需要为Spring IoC设计一个...

weixin_44103200的博客 215

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

JavaEE——Spring Web MVC启动流程

JavaEE——Spring Web MVC启动流程 摘要: web容器正是通过ContextLoaderListener和dispatcherServlet这两个配置才和spring管理起来。ContextLoaderListener与web容器的ServletContext关联,为Spring的IOC容器提供了一个宿主环境。在建立起IOC容器体系之后,把DispatcherServlet作...

sinat_41518495的博客 828

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

IOC容器在web容器中初始化过程——(二)深入理解Listener方式装载IOC容器方式...

先来看一下ContextServletListener的代码 public class ContextLoaderListener extends ContextLoader implements ServletContextListener { public ContextLoaderListener() { } public ContextLoad...

QQ18324429562的博客 211

spring源码---mvc:初始化

一,九大组件 1.handlerMapping 用来查找handler的,也就是处理器,对应的就是标签@RequestMapping。也就是说handler,可以是类,也可以是方法. 2.handlerAdapter 我们最原始的servlet处理方式可以知道,当一个请求到达的时候,是封装成request发送到servlet的doService(HttpServletRequest,HttpServletResponse)形式的,所以,要从传统的servlet模式转到spring m...

阿七 382

spring中的Web上下文(ServletContext),Spring上下文(WebApplicationContext),SpringMVC上下文

Servlet规范定义了一个API标准,这一标准的实现通常称为Servlet容器,比如开源的Tomcat、JBoss。 web容器更准确的说应该叫web服务器,它是来管理和部署 web应用的。web容器最典型的就是tomcat了,Tomcat是web容器也是servlet容器。所谓容器(服务器、中间件等),就是提供一些底层的、业务无关的基本功能,为真正的Servl...

ystyaoshengting的专栏 2331

Spring MVC与Web环境(一):IOC容器在Spring MVC中的启动

            在原书的阅读中我们可以看到,Spring并不是天生就能在Web容器中起作用的。我们同样需要把我们的IoC容器手动添加到Web容器中,也就是在web.xml文件中配置一些基础的类比如DispatcherServlet,ContextLoaderListener这些我们熟悉的类。当这些类的配置完成之后,启动tomcat。就会在IoC容器中生成这些处理我们请求的bean。在Dis...

SmilingCobra 408

Web容器-->Spring IOC容器

Java web容器的启动与处理请求的过程 1.启动一个web项目的时候,web容器回去读取它的配置文件web.xml,读取结点。 2.容器创建一个servletContext(Servlet上下文),这个web项目的所有部分都将共享这个上下文。 3.容器将转换为键值对,并交个ServletContext。因为listener,filter等组件在初始化时会用到这些上下文的信息,所以要先加载。 4.容器创建的类实例,创建监听器。 5.加载filter和servlet load-on-startup元素在we

weixin_41942838的博客 295

Spring mvc web 配置

Spring Framework本身没有Web功能, Spring MVC使用WebApplicationContext类扩展ApplicationContext ,使得拥有web功能。那么,Spring MVC是如何在web环境中创建IoC容器呢?web环境中的IoC容器的结构又是什么结构呢?web环境中,Spring IoC容器是怎么启动呢? 以Tomcat为例,在Web容器中使用...

weixin_30808253的博客 79

Tomcat启动带动Spring IoC容器启动流程源码分析

Tomcat启动带动Spring IoC容器启动流程源码分析目录概述原理概述相关工具如下:分析:小结:参考资料和推荐阅读 LD is tigger forever,CG are not brothers forever, throw the pot and shine forever. Modesty is not false, solid is not naive, treacherous but not deceitful, stay with good people, and stay away

专注Java(全栈)应用开发,求知若渴,虚心若愚,talk is cheap, show me the code. 654

深入理解spring mvc启动过程与原理

​spring mvc的启动,是跟随着tomcat启动的,所以要深入理解spring mvc的启动过程与原理,需要先了解下tomcat启动的一些关键过程。1、tomcat web应用启动及初始化过程参考官方文档,tomcat web应用启动过程是这样的:​图1 tomcat web应用启动过程大概意思就是,当一个Web应用部署到容器内时,在web应用开始执行用户请求前,会依次执行以下步骤:部署描述文件web.xml中元素标记的事件监听器会被创建和初始化;对于所有事件监听器,如果实现了Se

m0_69804655的博客 423

Spring springmvc 的启动流程

       Spring的启动是建筑在servlet容器之上的,所有web工程的初始位置就是web.xml,它配置了servlet的上下文(context)和监听器(Listener),下面就来看看web.xml里面的配置:     &lt;web-app&gt;            &lt;welcome-file-list&gt;             &lt;welcome-file...

踏浪归来 9146

springMVC中spring容器启动流程

springMVC中spring容器启动过程,从web.xml配置文件开始分析。 org.springframework.web.context.ContextLoaderListener ContextLoaderListener监听ServletContex的初始化,ServletContext初始化的时候调用继承自ContextLoader的initWebApplicatio

a1240302901的专栏 1754
上一篇: J2EE 简介
下一篇: 【微服务】Dubbo 和 Spring Cloud 比较
TaiSung
博客等级 码龄15年 49粉丝 132原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值