springmvc源码之Web上下文初始化

news2024/10/6 6:50:17

系列文章目录

springmvc源码之Web上下文初始化


文章目录

  • 系列文章目录
    • Web上下文初始化
      • ContextLoaderListener
        • initWebApplicationContext初始化
          • 创建WebApplicationContext上下文


Web上下文初始化

web上下文与SerlvetContext的生命周期应该是相同的,springmvc中的web上下文初始化是由ContextLoaderListener来启动的

在这里插入图片描述

在web.xml中配置ContextLoaderListener

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
</context-param>

ContextLoaderListener

ContextLoaderListener实现了ServletContextListener接口,ServletContextListener是Servlet定义的,提供了与Servlet生命周期结合的回调,contextInitialized方法和contextDestroyed方法;ContextLoaderListener继承了ContextLoader类,通过ContextLoader来完成实际的WebApplicationContext的初始化工作,并将WebApplicationContext存放至ServletContext中,ContextLoader就像是spring应用在web容器中的启动器

从spring3.x起就不需要配置监听器ContextLoaderListener,只需要配置DispatcherServlet就可以了

public class ContextLoaderListener extends ContextLoader implements ServletContextListener {

   /**
    * Initialize the root web application context.
    */
  // ServletContext被创建时触发,初始化web上下文
   @Override
   public void contextInitialized(ServletContextEvent event) {
      initWebApplicationContext(event.getServletContext());
   }

   /**
    * Close the root web application context.
    */
  // ServletContext被销毁时触发,关闭web上下文
   @Override
   public void contextDestroyed(ServletContextEvent event) {
      closeWebApplicationContext(event.getServletContext());
      ContextCleanupListener.cleanupAttributes(event.getServletContext());
   }

}

在启动时会创建一个WebApplicationContext作为IOC容器,默认的实现类是XmlWebApplicationContext

/** Default config location for the root context */
// 默认的配置位置,如果不进行配置,就会读取这个文件
public static final String DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml";

/** Default prefix for building a config location for a namespace */
// 配置文件默认在/WEB-INF/目录下
public static final String DEFAULT_CONFIG_LOCATION_PREFIX = "/WEB-INF/";

/** Default suffix for building a config location for a namespace */
// 配置文件默认后缀名是.xml
public static final String DEFAULT_CONFIG_LOCATION_SUFFIX = ".xml";

initWebApplicationContext初始化

public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
  // WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE是WebApplicationContext.class.getName() + ".ROOT"
  // 如果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!");
   }

   Log logger = LogFactory.getLog(ContextLoader.class);
   servletContext.log("Initializing Spring root WebApplicationContext");
   
   long startTime = System.currentTimeMillis();

   try {
      // Store context in local instance variable, to guarantee that
      // it is available on ServletContext shutdown.
      if (this.context == null) {
        // 初始化context
         this.context = createWebApplicationContext(servletContext);
      }
      if (this.context instanceof ConfigurableWebApplicationContext) {
         ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
         if (!cwac.isActive()) {
            // The context has not yet been refreshed -> provide services such as
            // setting the parent context, setting the application context id, etc
            if (cwac.getParent() == null) {
               // The context instance was injected without an explicit parent ->
               // determine parent for root web application context, if any.
               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) {
      logger.error("Context initialization failed", ex);
      servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex);
      throw ex;
   }
   catch (Error err) {
      logger.error("Context initialization failed", err);
      servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, err);
      throw err;
   }
}
创建WebApplicationContext上下文
protected WebApplicationContext createWebApplicationContext(ServletContext sc) {
  // 如果在web.xml中有配置contextClass,则使用配置的类
  // 如果没有配置,则使用默认的配置 ContextLoader.properties
  // org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/23331.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

公众号免费查题

公众号免费查题 本平台优点&#xff1a; 多题库查题、独立后台、响应速度快、全网平台可查、功能最全&#xff01; 1.想要给自己的公众号获得查题接口&#xff0c;只需要两步&#xff01; 2.题库&#xff1a; 题库&#xff1a;题库后台&#xff08;点击跳转&#xff09; 题…

Flink概念及应用场景

1、Flink实时应用场景 Flink在实时计算领域内的主要应用场景主要分为四类&#xff1a; 实时数据同步流式ETL实时数据分析复杂事件处理2、实时数据体系架构 实时数据体现大致分为三类场景&#xff1a; 流量类业务类特征类在数据模型上&#xff0c;流量类是扁平化的宽表&…

论文管理系统(用户列表显示功能)

上次我们已经实现了论文管理系登录功能,这次我们要实现登录之后的跳转到首页,并且让首页列表显示出数据库的信息并在Mapper中写入模糊查询功能语句,这次我们不使用MybatisPlus写这个功能,这次使用Mybatis来写,区别就是Plus是继承于<BaseDAO>Mapper,而Mybatis则是我们通过…

JAVASE(复习)——static

static 关键字是静态的意思,是Java中的一个修饰符,可以修饰成员方法,成员变量 一、被static修饰的特点 被类的所有对象共享&#xff08;在堆内存共享&#xff09; 随着类的加载而加载&#xff0c;优先于对象存在&#xff08;就是你加载类的时候就加载了&#xff09; 可以通过…

@Transactional注解为何会失效

使用 Transactional 注解能保证方法内多个数据库操作要么同时成功、要么同时失败。但是有很多细节需要注意&#xff0c;不然Transactional可能会失效。 1.注解应用在非 public 的方法上 如果Transactional注解应用在非public 修饰的方法上&#xff0c;Transactional将会失效。…

FLink源码 1.13 3 种 命令客户端 Generic CLI 、 yarn-cluster、DefaultCLI使用

先说结论:对于三种Cli,Generic CLI mode、yarn-cluster mode、default mode,无法同时使用,源码使用顺序为Generic CLI mode优先判断,接着是 yarn-cluster mode ,最后是default mode,所以对于三种Cli的参数,不能混用,否则会出现命令不生效的情况,具体使用以及源码见下…

【滤波跟踪】基于matlab扩展卡尔曼滤波的无人机路径跟踪【含Matlab源码 2236期】

⛄一、EKF算法简介 扩展卡尔曼滤波是利用泰勒级数展开方法将非线性滤波问题转化成近似的线性滤波问题,利用线性滤波的理论求解非线性滤波问题的次优滤波算法。其系统的状态方程和量测方程分别如式(1)、式(2)所示: 式中,X(k)为n维的随机状态向量序列,Z(k)为n维的随机量测向量序…

Matlab 对连续时间信号的运算

Matlab 对连续时间信号的运算 1、连续时间系统零状态响应 题目&函数说明 连续时间系统的微分方程为 y"(t) 4y’(t) 3y(t) f’(t) 2f(t) 当 输入信号 f(t) 20e-2tu(t) 时&#xff0c;初始值 y(0-) 2, y’(0-) 1, 求系统的零状态响应 Matlab 库函数中的 lsim(…

GNN Tensorflow packages

tf framework定义 tf.name_scope()函数 tf.name_scope(name)&#xff0c;用于定义python op的上下文管理器。 此上下文管理器将推送名称范围&#xff0c;这将使其中添加的所有操作的名称带有前缀。 例如&#xff0c;定义一个新的Python op my_op&#xff1a; def my_op(a,…

scratch踢足球 电子学会图形化编程scratch等级考试一级真题和答案解析2022年9月

目录 scratch踢足球 一、题目要求 1、准备工作 2、功能实现 二、案例分析

代码随想录算法训练营第三十九天| LeetCode62. 不同路径、LeetCode63. 不同路径 II

一、LeetCode62. 不同路径 1&#xff1a;题目描述&#xff08;62. 不同路径&#xff09; 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下…

python 视角下的 6 大程序设计原则

众所周知&#xff0c;python 是面向对象的语言。 但大多数人学习 python 只是为了写出“能够实现某些任务的自动化脚本”&#xff0c;因此&#xff0c;python 更令人熟知的是它脚本语言的身份。 那么&#xff0c;更近一步&#xff0c;如果使用 python 实现并维护一个大的项目…

基于SpringBoot的CSGO赛事管理系统

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SpringBoot 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目…

为研发效能而生|一场与 Serverless 的博弈

2022 年 11 月 3 日&#xff0c;第三届云原生编程挑战赛即将迎来终极答辩&#xff0c;18 支战队、32 位云原生开发者入围决赛&#xff0c;精彩即将开启。 云原生编程挑战赛项目组特别策划了《登顶之路》系列选手访谈&#xff0c;期待通过参赛选手的故事&#xff0c;看到更加生…

第1章 计算机系统概述

1.1 操作系统的基本概念 1.1.1 操作系统的概念 操作系统是计算机系统中最基本的系统软件。 操作系统&#xff08;Operating System&#xff0c;OS&#xff09;是指控制和管理整个计算机系统的硬件与软件资源&#xff0c;合理地组织、调度计算机的工作与资源的分配&#xff0c;进…

锐捷端口安全实验配置

端口安全分为IPMAC绑定、仅IP绑定、仅MAC绑定 配置端口安全是注意事项 如果设置了IPMAC绑定或者仅IP绑定&#xff0c;该交换机还会动态学习下联用户的MAC地址 如果要让IPMAC绑定或者仅IP绑定的用户生效&#xff0c;需要先让端口安全学习到用户的MAC地址&#xff0c;负责绑定不生…

如何参与一个开源项目!

今天教大家如何给开源项目提交pr&#xff0c;成为一名开源贡献者。pr是 Pull Request 的缩写&#xff0c;当你在github上发现一个不错的开源项目&#xff0c;你可以将其fork到自己的仓库&#xff0c;然后再改动一写代码&#xff0c;再提交上去&#xff0c;如果项目管理员觉得你…

【建议收藏】回收站数据恢复如何操作?3个方案帮你恢复删除的文件

在使用电脑时&#xff0c;我们经常会清理不需要的文件数据。电脑回收站被清空了&#xff0c;但是里面有我们重要的数据&#xff0c;回收站数据恢复如何操作&#xff1f;不如试试下面的3个方案&#xff0c;一起来了解一下回收站数据恢复吧&#xff01; 一、注册表恢复回收站数据…

电脑视频转换成mp4格式,视频格式转换器转换

怎么把电脑视频转换成mp4格式&#xff1f;使用视频转换器&#xff0c;可以转换来自各种设备的音视频格式&#xff0c;包括相机、手机、视频播放器、电视、平板电脑等。因此&#xff0c;音视频爱好者都可以使用它在各种设备上播放或在社交平台上分享。 主要人群及作用&#xff1…

BHQ-2 NHS,916753-62-3作为各种荧光共振能量转移DNA检测探针中淬灭部分

英文名称&#xff1a;BHQ-2 NHS CAS&#xff1a;916753-62-3 外观&#xff1a;深紫色粉末 分子式&#xff1a;C29H29N7O8 分子量&#xff1a;603.59 储存条件&#xff1a;-20C&#xff0c;在黑暗中 结构式&#xff1a; 凯新生物产品简介&#xff1a; 黑洞猝灭剂-2&#…