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
如何利用ADS中的耦合线设计带通滤波器并转换为HFSS模型 耦合线带通滤波器是一种常用的微带滤波器形式,由多个长度为四分之一波长的耦合线节组成,在所需频点形成谐振,构成滤波器的频率响应特性。首先我们先来了解一下耦合线带通滤波器的电路结构,见下图:包括两对耦合线,中间为公共连接点,其中两对耦合线的偶奇模阻抗为(Z1e,Z1o)和(Z2e,Z2o,端口输入阻抗为Z0)。2.指定一个初始奇偶模值,ADS优化出一个合适的结果,通过奇偶模值利用linecalc工具计算出微带耦合线尺寸。假设中心频率为2GHz,则对应频点的电长度为。5.运行结果,两个软件仿真结果基本一致。 阅读详情

相关推荐

Redis+Unity 数据库搭建

游戏中需要存放排行榜等数据,而且是实时存放,所以就涉及到数据库的问题。这里找服务器大神了解到可以用Redis来做存储,免费的效率极高。

chaixinke的专栏 878

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

第7篇-SAP MM模块-JIT应用实战解析,从计划协议到JIT供应的关键配置与流程

本文深入解析SAP MM模块中的JIT(Just In Time)供应模式,从计划协议到JIT供应的关键配置与流程。通过动态计划行管理、需求聚合与分解等核心功能,实现精确数量、时间和地点的物料供应。文章详细介绍了主数据准备、计划协议配置、MRP参数精调及EDI集成方案,并提供了实施中的典型问题与解决方案,助力企业优化供应链管理。

weixin_30363509的博客 947

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

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

weixin_39616339的博客 446

MATLAB双目相机标定:从工具箱实战到参数精解

本文详细讲解了使用MATLAB进行双目相机标定的完整实战流程与参数精解。从拍摄合格的棋盘格图像、设置关键参数(如径向畸变系数),到分析重投影误差、优化结果并正确导出和使用内外参,提供了从操作到原理的全面指导,帮助读者为立体视觉应用奠定精准基础。

weixin_29041767的博客 257

WslRegisterDistribution failed with error_ 0x8007019e、0x800701bc、0x80370102

Ubuntu 20.04.4 LTS 报错解决方案。分别涉及到三个错误:WslRegisterDistribution failed with error: 0x8007019e、WslRegisterDistribution failed with error: 0x800701bc和WslRegisterDistribution failed with error: 0x80370102

一起加油~ 5万+

windows服务的停止和开启

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

weixin_30600197的博客 413

保姆级教程:在瑞芯微RV1126B上部署轻量化YOLOv8,实现端侧实时目标检测

本文详细介绍了在瑞芯微RV1126B芯片上部署轻量化YOLOv8模型的完整流程,包括开发环境搭建、模型训练优化、量化转换及嵌入式部署。通过利用RV1126B的3TOPS NPU算力和AI-ISP特性,实现端侧实时目标检测,提升边缘AI应用的性能和效率。

weixin_30329623的博客 266

windows下快速启动和停止服务

在windiws下启动某一个服务其实是很头疼的一件事,比如要启动和停止mysql服务,或者是oracle服务,我们一般的做法是打开管理工具----找到对应的服务再手动打开或者停止,如果电脑的配置比较高,运行速度比较快还是可以忍受的,反之,感觉做这件事是件漫长的事! 快速启动和停止服务,我整理了如下几个步骤: 控制面板----管理工具----服务----双击我们要操作的服务----复制服

最初的梦想 2227

4、硬件工程师笔试面试知识器件篇——电阻(2025版本)

本文系统介绍了电阻的基础知识与应用。首先阐述了电阻的定义、工作原理及类型(固定/可变电阻),详细说明了常见电阻材料(碳膜、金属膜、线绕等)的特性与标记方法。重点分析了电阻在电路设计中的关键参数:功率计算需考虑1.5-2倍安全裕度,温度系数影响电路稳定性。文章还对比了不同封装形式(轴向/贴片/功率封装等)的适用场景,特别强调高功率电路需选择专用封装并做好散热设计。最后指出电路仿真可优化电阻选择,并列举了相关电子元件在设计中同样需要仿真验证。全文为硬件工程师提供了电阻选型的实用指导。

XU157303764的博客 5204

人工智能在软件测试中的广泛应用领域

人工智能在软件测试中的应用领域涵盖了自动化测试、缺陷预测和缺陷检测、智能化测试报告生成等方面。以上提供的示例代码只是其中的一小部分,实际上,人工智能在软件测试中还有许多其他的应用。通过结合人工智能和软件测试,可以提高测试效率和质量,减少测试工作的人力成本,并帮助开发人员更好地理解和改进软件产品。人工智能(Artificial Intelligence,简称AI)在软件测试领域的应用越来越广泛。下面将介绍几个人工智能在软件测试中的主要应用领域,并提供一些相关的源代码示例。

FycPerformance的博客 462

Tomcat运维

tomcat从安装到项目部署

pdp1196431288的博客 2468

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

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

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

XXX 1663

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

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

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.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

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

JavaEE——Spring Web MVC启动流程

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

sinat_41518495的博客 828

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. 653

深入理解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

Spring MVC启动整体过程

一Spring配置 contextConfigLocation /WEB-INF/spring/applicationContext.xml org.springframework.web.context.ContextLoaderListener spring前端控制器DispatcherServlet --> mvc-dis

李平安 530
上一篇: 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、付费专栏及课程。

余额充值