【Spring MVC学习】WebApplicationContext初始化的三种方式

Spring源码学习(六):Spring MVC的初始化过程 目录 1.ContextLoaderListener 1.1创建WebApplicationContext 1.2设置和刷新WebApplicationContext 2.DispatcherServlet 2.1init方法 2.2initServletBean方法 2.3 OnRefresh方法 3.九大组件的注册 3.1文件上传解析器MultipartResolv... 阅读详情

ApplicationContext是Spring的核心,Context我们通常解释为上下文环境,我想用“容器”来表述它更容易理解一些,ApplicationContext则是“应用的容器”了;在Web应用中,我们会用到WebApplicationContext,WebApplicationContext继承自ApplicationContext;WebApplicationContext的初始化方式和BeanFactory.ApplicationContext有所区别,因为WebApplicationContext需要ServletContext实例,也就是说它必须拥有Web容器的前提下才能完成启动的工作.有过Web开发经验的读者都知道可以在web.xml中配置自启动的Servlet或定义Web容器监听器(ServletContextListener),借助着两者中的任何一个,我们就可以启动Spring Web应用上下文的工作.

Spring分别提供了用于启动WebApplicationContext的Servlet和Web容器监听器:

org.springframework.web.context.ContextLoaderServlet;

org.springframework.web.context.ContextLoaderListener.
  • 1
  • 2
  • 3

这两个方法都是在web应用启动的时候来初始化WebApplicationContext,我个人认为Listerner要比Servlet更好一些,因为Listerner监听应用的启动和结束,而Servlet得启动要稍微延迟一些,如果在这时要做一些业务的操作,启动的前后顺序是有影响的。

配置例子如下:

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> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

那么在ContextLoaderListener和ContextLoaderServlet中到底做了什么呢? 
以ContextLoaderListener为例,我们可以看到

public class ContextLoaderListener implements ServletContextListener {  

    private ContextLoader contextLoader;  

    /** 
     * Initialize the root web application context. 
     */  
    public void contextInitialized(ServletContextEvent event) {  
        this.contextLoader = createContextLoader();  
        this.contextLoader.initWebApplicationContext(event.getServletContext());  
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

显然,ContextLoaderListener实现了ServeletContextListenet,在ServletContext初始化的时候,会进行Spring的初始化,大家肯定会想,Spring的初始化应该与ServletContext有一定关系吧?有关系吗?接下来让我们看看 
ContextLoader.initWebApplicationContext方法。

ContextLoader是一个工具类,用来初始化WebApplicationContext,其主要方法就是initWebApplicationContext,我们继续研究initWebApplicationContext这个方法:

public WebApplicationContext initWebApplicationContext(ServletContext servletContext)  throws IllegalStateException, BeansException {  

            //从ServletContext中查找,是否存在以WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE为Key的值

    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!");  
    }  


    try {  
        // Determine parent for root web application context, if any.  
        ApplicationContext parent = loadParentContext(servletContext);  

        // it is available on ServletContext shutdown.  
        this.context = createWebApplicationContext(servletContext, parent);  
        //将ApplicationContext放入ServletContext中,其key为<WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE 


    servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context); 
                //将ApplicationContext放入ContextLoader的全局静态常量Map中,其中key为:Thread.currentThread().getContextClassLoader()即当前线程类加载器 

        currentContextPerThread.put(Thread.currentThread().getContextClassLoader(), this.context);  

        return this.context;  
    }  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

从上面的代码大家应该明白了Spring初始化之后,将ApplicationContext存到在了两个地方(servletContext中和currentContextPerThread中),那么是不是意味着我们可以通过两种方式取得ApplicationContext?

第一种获取方式:

 注:WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";
即为 "org.springframework.web.context.WebApplicationContext.ROOT"
  • 1
  • 2

那么咱们是不是可以这样获得ApplicationContext:

request.getSession().getServletContext().getAttribute("org.springframework.web.context.WebApplicationContext.ROOT")  
  • 1

确实可以,而且我们想到这种方法的时候,Spring早就提供给我们接口了:

public abstract class WebApplicationContextUtils {  

public static WebApplicationContext getRequiredWebApplicationContext(ServletContext sc)  throws IllegalStateException {  

        WebApplicationContext wac = getWebApplicationContext(sc);  
        if (wac == null) {  
            throw new IllegalStateException("No WebApplicationContext found: no ContextLoaderListener registered?");  
        }  
        return wac;  
    }  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

getWebApplicationContext方法如下:

public static WebApplicationContext getWebApplicationContext(ServletContext sc) {  
        return getWebApplicationContext(sc, WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);  
    }  
  • 1
  • 2
  • 3
  • 4

第二种方法:

前面说到Spring初始化的时候,将ApplicationContext还存了一份到ContextLoader的Map里面,那么我们是不是可以通过Map.get(key) ???很不幸的是,这个Map是私有的。

private static final Map currentContextPerThread = CollectionFactory.createConcurrentMapIfPossible(1);  
  • 1
  • 2

Spring为我们提供了方法:

public static WebApplicationContext getCurrentWebApplicationContext() {  
        return (WebApplicationContext) currentContextPerThread.get(Thread.currentThread().getContextClassLoader());  
    }  
  • 1
  • 2
  • 3
  • 4

第二种方法与第一种方法相比有什么好的地方呢?就是它不需要参数,只要在Web容器中,当Spring初始化之后,你不需要传入任何参数,就可以获得ApplicationContext。不过这个方法在Spring2.52版本中是不存在的,但是在2.5.5版本中提供了。

其实第二种获取方法看上去简单,但他的原理还是有一定难度的,他与类加载器的线程上下文相关,这个线程上下文在咱们常用的Mysql驱动中有用到。

第三种方式:

借用ApplicationContextAware,ApplicationContext的帮助类能够自动装载ApplicationContext,只要你将某个类实现这个接口,并将这个实现类在Spring配置文件中进行配置,Spring会自动帮你进行注入 ApplicationContext.ApplicationContextAware的代码结构如下:

public interface ApplicationContextAware {  

        void setApplicationContext(ApplicationContext applicationContext) throws BeansException;  

}  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

就这一个接口。可以这样简单的实现一个ApplicationContextHelper类:

public class ApplicationHelper implements ApplicationContextAware {  


    private ApplicationContext applicationContext; 

    public void setApplicationContext(ApplicationContext applicationContext)  
            throws BeansException {  
            this.applicationContext = applicationContext;  
    }  


    public  ApplicationContext getApplicationContext(){
        return this.applicationContext;  
    }  
}  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

通过ApplicationHelper我们就可以获得咱们想要的AppilcationContext类了。

ERPS协议原理 目录 1、ERPS概述: 2、ERPS名词概念解释: 3、ERPS协议报文: 4、ERPS单环基本原理: 5、单环多实例原理: 6、多环原理: 1、ERPS概述: ERPS(Ethernet Ring Protection Switching),即以太网多环保护技术,是ITU-T定义的一种二层破环协议标准,标准号为ITU-T G.8032/Y1344,因此又称为G.8032。它定义了RAPS(Ring Auto Protection Switching)协议报文和保护倒换机制。 ERPS目前支持v1和v2两 阅读详情

相关推荐

保姆级教程:用CANoe的LIN Slave Conformance Tester搞定一致性测试(附LDF配置避坑点)

本文详细介绍了如何使用CANoe的LIN Slave Conformance Tester进行汽车电子LIN从节点一致性测试,包括测试环境搭建、LDF文件配置、多通道测试技巧及常见问题解决方案。通过实战案例和高级配置技巧,帮助工程师高效完成测试任务,确保LIN总线通信的可靠性。

weixin_30385925的博客 528

Cannot initialize context because there is already a root application context present

一、问题 Cannot initialize context because there is already a root application context present - check whether you have multiple ContextLoader* definitions in your web.xml! 二、问题描述 在自定义spring-boot的启动监听器时...

JackiAndroid的专栏 3313

四参数与七参数坐标转换含义及区别

一.前言 不同坐标系,其椭球体的长半径,短半径和扁率是不同的。比如我们常用的四种坐标系北京54、西安80、WGS84、CGCS2000所对应的椭球体,它们的椭球体参数就各不相同。而不同空间直角坐标系之间的转换一般通过七参数或者四参数来实现坐标转换。 二.四参数转换 两个不同的二维平面直角坐标系之间转换通常使用四参数模型,四参数适合小范围测区的空间坐标转换,相对于七参数转换的优势在于只需要2个公共已知点就能进行转换,操作简单。 在该模型中有四个未知参数,即: (1)两个坐标平...

尘海折柳的博客 1万+

spring boot遇到的问题

1.cannot initialize context because there is already a root application context present - check whether you have multiple contextloader* definitions in your web.xml! 解决方案:我这个工程spring boot里没有web.xml。 ...

baicp3的专栏 1880

扣子(coze)案例^第22期:零代码打造小红书竞品监控系统+AI自动生成运营策略建议

本文详细介绍了如何利用扣子(coze)平台零代码搭建小红书竞品监控系统。该系统通过自动化工作流抓取竞品笔记数据,并存入飞书多维表格,结合AI能力自动生成包含可视化分析报告在内的运营策略建议,帮助运营者高效进行数据驱动的市场分析。

weixin_29313239的博客 1007

Python 高级语法:闭包

闭包(Closure)是函数式编程中的一个重要概念。在Python中,闭包可以简单理解为:一种特殊的函数。外函数:嵌套函数中最外层的函数称之为外函数。内函数:嵌套函数中最内层的函数称之为内函数;内函数引用了外函数的临时变量;外函数的返回使用了临时变量的内函数。

moment159的博客 2354

Spring源码阅读之WebapplicationContext初始化

Spring源码阅读之WebapplicationContext初始化 ​ 当一个Web应用在服务器(tomcat)中启动的时,tomcat需要给该应用创建一个ServletContext对象作为公共容器保存了应用中的配置信息。这些配置信息是通过读取web.xml文件中的标签来获取的。 ​ 应用在tomcat中启动时,首先会读取web.xml中两个标签节点<context-param>、<listener>并创建ServletContext对象,将context-param标签中

qq_38238296的博客 851

鸿蒙读书笔记1:《鸿蒙操作系统设计原理与架构》

GUI、 语 音 控 制 方 式 的 VUI(Voice User Interface, 语 音 用 户 界。电话、多媒体、DFX、MSDP(Multimodal Sensor Data Platform,多。面)、手势/姿态控制的CVUI(Computer Vision User Interface,计算。KAL(Kernel Abstract Layer,内核抽象层)通过屏蔽多内核差异,JavaScript、C、C++等多语言的用户程序开发框架,以及UI框架、

jackyrongvip的专栏 2451

Spring MVC之WebApplicationContext 容器的初始化

因为spring-mvc项目,是的子项目,所以需要拉取整个工程,包含 Spring 所有的子项目。

Coder_Boy_的博客 1227

君正T31x metartc集成测试

metartc为国内杨大侠部分开源的一款用于嵌入式领域webrtc库,它与谷歌官方webrtc相比,编译到君正平台的可执行文件仅有5M即可实现webrtc的通信。1. 目前实现的是基于开源版v5.0-b0版本做的简单修改,官方的好几个版本都多少缺点东西,我这里给整理了一下。目前是局域网连接的webrtc,后续尝试走stun和turn试一下NAT穿越的效果。

fsmpeg的博客 3160

YOLOv13|损失函数优化篇:Focal EIOU 保持良好性能的同时,提供更高效的计算和更稳定的训练过程-包源码

Focal IoU与EIoU:目标检测中的损失函数优化 摘要:本文深入探讨了目标检测中两种重要的边界框回归损失函数优化方法。Focal IoU借鉴Focal Loss思想,通过(1-IoU)^γ因子调节损失权重,使模型更关注难样本(低IoU预测框),有效解决了传统IoU Loss对难易样本权重相同的问题。EIoU则在CIoU基础上改进,通过简化长宽比计算、分离宽高损失项,提升了计算效率和训练稳定性。两种方法分别从样本权重分配和损失函数结构优化角度,显著提升了目标检测性能,为实际应用提供了更高效的解决方案。文

FJN110的博客 1865

Spring MVC源码——Root WebApplicationContext

Spring MVC源码——Root WebApplicationContext   打算开始读一些框架的源码,先拿 Spring MVC 练练手,欢迎点击这里访问我的源码注释, SpringMVC官方文档一开始就给出了这样的两段示例:    public class MyWebApplicationInitializer implements WebApplicationInitial...

胡峻峥的博客 1892

uniapp - [微信小程序] 实现点击预览各种文件 pdf文档、视频mp4、mp3音乐、图片图像、word/excel/ppt 等,uniapp小程序文件预览功能(详细示例代码,一键复制开箱即用)

uniapp,uniapp微信小程序,支付宝小程序平台端,uniapp实现文件在线预览,uniapp微信小程序怎么实现预览视频mp4,mp3音乐,图片,office文档,小程序平台如何在线预览word/excel/ppt文档,uniapp实现小程序端的文件查看功能,uniapp小程序端实现pdf文件预览,uniapp纯前端预览PDF、DOC、DOCX、图片、视频,uni-app文档、图片预览查看,uniapp文档预览功能,uniapp小程序端文件预览,uniapp小程序平台纯前端解析word,pdf,xls

✅ 精选推荐文章 1万+

[spring-mvc] webApplicationContext

Spring中的Application实例是可以有范围(scope)的。在Spring MVC中,每个dispatcherServlet都持有一个自己的上下文对象WebApplicationContext,它又继承了根(root)WebApplicationContext对象已经定义的所有bean。这些继承的bean可以在具体的Servlet实现中被重载,在每个Servlet实例中你也可以定义其sc

weixin_36210698的博客 637

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

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

IEM模型,地表粗糙度模拟

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

Spring MVC源码——Servlet WebApplicationContext

目录 Spring MVC源码——Servlet WebApplicationContext HttpServletBean FrameworkServlet Spring MVC源码——Servlet WebApplicationContext 上一篇笔记中记录了...

weixin_30642029的博客 70

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Spring WebApplicationContext初始化

如果要在我们的javaweb项目中引入Spring框架,首先我们需要将我们需要引入的Spring对应版本的jar包引入到我们的项目工程中,我这里是使用maven来管理jar包的,所以需要在pom.xml文件中添加如下依赖配置:     org.springframework     spring-webmvc      4.3.0.RELEASE 注:我这里使用的Spring版

小儍鈲的专栏 2121

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Spring MVC源码分析 之 Root WebApplicationContext 容器

1、在开始看具体的源码实现之前,我们先一起来看看现在“陌生”的 web.xml 配置。代码如下: 在排列顺序上一点要按照<context-param>、<filter><filter-mapping>、<listener>、<servlet><servlet-mapping> 这样的顺序进行配置不然会报错 &l...

weixin_41076930的博客 695

spring mvc 源码研究简单笔记--web容器启动加载WebApplicationContext和初始化DispatcherServlet

Web容器启动时,ContextLoaderListener实现了ServletContextListener接口,即在Servlet初始化阶段,会通知ContextLoaderListener监听器,初始化 Context容器,这里使用到了ServletContext的初始化参数。即在web.xml配置的context-param 1.首先查找配置的WebApplicationContext实例,通过默认配置或用户在web.xml配置的contextClass实现类,并实例化对象这里使用的是XmlWebA

zghwaicsdn的专栏 6689

Spring系列-Spring MVC初始化流程

什么是Spring MVC? Spring MVC是java的web框架,不过在说Spring MVC之前,先说下MVC和三层架构吧,我们在web开发中,经常用到MVC模式,这个MVC指的是: Model(数据模型) + View(视图) + Controller(控制器),MVC模式在UI设计中使用非常普遍,主要特点是分离了模型,视图,控制器三种角色,将业务处理从UI设计中独立出来,使得相互之间...

山楂树的博客 486

spring mvc初始化及其原理

Spring MVC启动过程大致分为两个过程: 1、ContextLoaderListener初始化,实例化IoC容器,并将此容器实例注册到ServletContext中。 2、DispatcherServlet初始化。 1. listener             org.springframework.web.context.ContextLoaderListener

snail_bi的博客 921

容器的初始化之 Servlet WebApplicationContext 容器

在开始之前,我们还是回过头看一眼web.xml的配置。代码如下: 即,ServletWebApplicationContext 容器的初始化,是在 DispatcherServlet 初始化的过程中执行。 HttpServletBean ,负责将 ServletConfig 设置到当前 Servlet 对象中。类上的简单注释如下: FrameworkServlet ,负责初...

yingzi19911010的博客 530

Spring MVC源码学习之DispatcherServlet初始化

Servlet生命周期(回顾) 1.servlet容器在收到第一个http请求之后会初始化对应的servlet调用init()方法 初始化的servlet是单例的,在web.xml在配置多少个servlet就会有多少个servlet实例 在web.xml中配置servlet时配置<load-on-startup>1</load-on-startup>会在容器启动 时初...

zippo_zu的博客 313
上一篇: Jquery string 和 json相互转换的方法
下一篇: SpringMVC容器初始化篇----ContextLoaderListener
ole_triangle_java
博客等级 码龄10年 82粉丝 83原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值