解析 SpringMVC 父子容器及九大内置组件加载过程

本文涉及的产品
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
简介: 解析 SpringMVC 父子容器及九大内置组件加载过程

在解析整个 mvc 父子容器加载过程时,先了解一些基本的流程和知识,Spring MVC 启动需要 Tomcat 容器来进行嵌入,启动 Tomcat 容器->加载项目的 web.xml 文件->启动 Spring 容器->启动 Spring MVC 容器.

Tomcat 安装启动及 idea 如何配置可以搜索网上其他文章进行构建.

web.xml 入口

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-config.xml</param-value>
    </context-param>
    <servlet>
        <servlet-name>mvc-test</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--SpringMVC 配置文件 -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:applicationContext.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
        <async-supported>true</async-supported>
    </servlet>
    <servlet-mapping>
        <servlet-name>mvc-test</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
</web-app>

<context-param> 标签 contextConfigLocation 参数 配置的是 Spring 父容器的配置文件,<servlet> 标签下 contextConfigLocation 参数配置的是 Spring MVC 子容器的配置文件,load-on-startup 配置为 1 或者 0 代表的是启动 Tomcat 容器后要进行 Servlet 加载及初始化,配置为 -1 代表只有请求 servlet 时才会被加载及初始化

父容器

ContextLoaderListener 上下文加载监听器这个类就至关重要了,tomcat 启动以后会调用该类下的初始化方法 contextInitialized,用于启动父容器,流程图如下所示:

contextInitialized 方法会调用其父类 ContextLoader#initWebApplicationContext 方法,其下有静态代码块用于加载 spring-web 模块下的 ContextLoader.properties 文件.

org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext
  • 首先当前的 ServletContext 中是否包含 .ROOT 字符,如果包含则抛出异常,提示 web.xml 不能多次定义 ContextLoader
  • 创建上下文对象,实例化 XmlWebApplicationContext 类型,其父类为 AbstractRefreshableWebApplicationContext,在其构造方法内会设置具体的展示名称:setDisplayName(“Root WebApplicationContext”),标识其为 ROOT 父容器
  • 最后,完成上下文的属性设置工作以及调用 refresh 方法完成 xml 文件解析、bean 实例化/初始化工作
  • 解析当前 web.xml 文件中是否配置了 contextId 初始化参数,如果有就设置 id 为 contextId 参数值,否则就拼接当前类名+上下文路径作为 id 名称.
  • 设置 ServletContext,类型为 ApplicationContextFacade,其类型为 tomcat catelina 包下的
  • 设置环境对象的属性资源变量值:servletContextInitParams、servletConfigInitParams 以及 SystemProperties、SystemEnv.
    到此,spring 父容器已经加载完毕.

子容器

父容器加载完毕,接下来还需要将 spring mvc 子容器进行加载工作,相信学习过 servlet 知识的同学都知道,init->service->destroy 这三个方法是执行或调用 servlet 所必须经过的历程,所以首先我们要先找到核心的方法 init,spring mvc 核心处理类:DispatcherServlet,观察其源码发现其并没有重写 init 方法,那么就可以观察它的父类,总会有实现 init 方法的父类.

通过前面给出的 web.xml 文件,servlet 标签下包裹的类型为:org.springframework.web.servlet.DispatcherServlet,其下还配置了 init-param 指向的 Spring MVC 子容器需要进行解析的 xml 配置文件,Spring MVC 子容器详细的加载流程图如下:

  1. 因为 DispatcherServlet 类没有对应的 init 方法,所以一直找它的父类,FrameworkServlet 内也没有 init 方法,所以还是找它的父类 HttpServletBean:在它下面有调用 init 方法进行容器的加载工作.
  2. Spring MVC 子容器创建时和父容器过程是一摸一样的,只是在属性上的设置做了一些区分的动作,例如:
    添加监听器 SourceFilteringListener 到 wac 中,实际是通过 ContextRefreshListener 去监听对应的事件:ContextRefreshedEvent,当监听器接收到消息之后会调用 onApplicationEvent 方法,执行 onRefresh 方法,将 refreshEventReceived 标志设置为 true,表示已经 refresh 过,该事件的处理主要的目的就是为了完成 Spring MVC 九大内置组件的加载工作.
    当执行 AbstractApplicationContext#refresh 方法内的 finshRefresh 时,会发布上下文的刷新事件,然后 FremeworkServlet.ContextRefreshListener 监听器就会接收到事件对其进行处理工作.
  3. 除了在执行 refresh 方法时会触发事件的发布,在 Spring MVC 子容器加载完以后,会判断 refreshEventReceived 标志是否为 false:如果是,代表还没进行刷新工作,会手动调用 DispatcherServlet#onRefresh 方法执行.

对以上内容进行总结:Spring MVC 启动是依赖于 Tomcat 服务的,所以整体的加载流程(启动 Tomcat->加载 web.xml 文件->Spring 容器->Spring MVC 容器)完成以后,后面就只需要对其进行调用了.

九大内置组件对象

加载 DispatcherServlet 类时,会执行 static 静态代码块,DispatcherServlet.properties 加载这个文件的属性源,在 spring-web-mvc 模块中,resource 目录下的 resources/org/springframework/web/servlet/DispatcherServlet.properties,其文件内容如下:

org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver
org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver
org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
  org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping,\
  org.springframework.web.servlet.function.support.RouterFunctionMapping
org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
  org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
  org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter,\
  org.springframework.web.servlet.function.support.HandlerFunctionAdapter
org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver,\
  org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\
  org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver
org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator
org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver
org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager

以下是 initStrageties 初始化策略器方法的执行流程图,如下:

  1. 初始化 MultipartResolver:主要用来处理文件上传,如果定义过当前类型的 bean 对象,那么直接获取,如果没有的话,可以为 null,一般使用的类:CommonsMultipartResolver
  2. 初始化 LocaleResolver:主要用来处理国际化配置,基于URL参数的配置(AcceptHeaderLocaleResolver),基于session的配置(SessionLocaleResolver),基于cookie的配置(CookieLocaleResolver)
  3. 初始化 ThemeResolver:主要用来设置主题 Theme,一般过节的时候,如:清明节或国家重要的节日,都是会切换主题背景的.
  4. 初始化 HandlerMapping 映射器:用来将对应的 request 跟 controller 进行对应
  5. 初始化 HandlerAdapter 处理适配器:主要包含 Http 请求处理器适配器,简单控制器处理器适配器,注解方法处理器适配器
  6. 初始化 HandlerExceptionResolver:基于 HandlerExceptionResolver 接口的异常处理
  7. 初始化 RequestToViewNameTranslator:当 controller 处理器方没有返回一个 View 对象或逻辑视图名称,并且在该方法中没有直接往 response 输出流里面写数据的时候,spring 将会采用约定好的方式提供一个逻辑视图名称
  8. 初始化 ViewResolver:将 ModelAndView 选择合适的视图进行渲染的处理器
  9. 初始化 FlashMapManager:提供请求存储属性,可供其他请求使用

总结

以上就是父子容器以及 Spring MVC 九大内置组件的加载过程详细解析.

如果觉得博文不错,关注我 vnjohn,后续会有更多实战、源码、架构干货分享!

大家的「关注❤️ + 点赞👍 + 收藏⭐」就是我创作的最大动力!谢谢大家的支持,我们下文见!

目录
相关文章
|
2月前
|
前端开发 JavaScript
React 步骤条组件 Stepper 深入解析与常见问题
步骤条组件是构建多步骤表单或流程时的有力工具,帮助用户了解进度并导航。本文介绍了在React中实现简单步骤条的方法,包括基本结构、状态管理、样式处理及常见问题解决策略,如状态管理库的使用、自定义Hook的提取和CSS Modules的应用,以确保组件的健壮性和可维护性。
83 17
|
1月前
|
Kubernetes Linux 虚拟化
入门级容器技术解析:Docker和K8s的区别与关系
本文介绍了容器技术的发展历程及其重要组成部分Docker和Kubernetes。从传统物理机到虚拟机,再到容器化,每一步都旨在更高效地利用服务器资源并简化应用部署。容器技术通过隔离环境、减少依赖冲突和提高可移植性,解决了传统部署方式中的诸多问题。Docker作为容器化平台,专注于创建和管理容器;而Kubernetes则是一个强大的容器编排系统,用于自动化部署、扩展和管理容器化应用。两者相辅相成,共同推动了现代云原生应用的快速发展。
209 11
|
2月前
|
前端开发 UED
React 文本区域组件 Textarea:深入解析与优化
本文介绍了 React 中 Textarea 组件的基础用法、常见问题及优化方法,包括状态绑定、初始值设置、样式自定义、性能优化和跨浏览器兼容性处理,并提供了代码案例。
102 8
|
2月前
|
负载均衡 网络协议 算法
Docker容器环境中服务发现与负载均衡的技术与方法,涵盖环境变量、DNS、集中式服务发现系统等方式
本文探讨了Docker容器环境中服务发现与负载均衡的技术与方法,涵盖环境变量、DNS、集中式服务发现系统等方式,以及软件负载均衡器、云服务负载均衡、容器编排工具等实现手段,强调两者结合的重要性及面临挑战的应对措施。
126 3
|
3月前
|
安全 持续交付 Docker
深入理解并实践容器化技术——Docker 深度解析
深入理解并实践容器化技术——Docker 深度解析
110 2
|
3月前
|
存储 安全 Java
Java多线程编程中的并发容器:深入解析与实战应用####
在本文中,我们将探讨Java多线程编程中的一个核心话题——并发容器。不同于传统单一线程环境下的数据结构,并发容器专为多线程场景设计,确保数据访问的线程安全性和高效性。我们将从基础概念出发,逐步深入到`java.util.concurrent`包下的核心并发容器实现,如`ConcurrentHashMap`、`CopyOnWriteArrayList`以及`BlockingQueue`等,通过实例代码演示其使用方法,并分析它们背后的设计原理与适用场景。无论你是Java并发编程的初学者还是希望深化理解的开发者,本文都将为你提供有价值的见解与实践指导。 --- ####
|
3月前
|
运维 持续交付 虚拟化
深入解析Docker容器化技术的核心原理
深入解析Docker容器化技术的核心原理
84 1
|
3月前
|
前端开发 JavaScript 开发者
揭秘前端高手的秘密武器:深度解析递归组件与动态组件的奥妙,让你代码效率翻倍!
【10月更文挑战第23天】在Web开发中,组件化已成为主流。本文深入探讨了递归组件与动态组件的概念、应用及实现方式。递归组件通过在组件内部调用自身,适用于处理层级结构数据,如菜单和树形控件。动态组件则根据数据变化动态切换组件显示,适用于不同业务逻辑下的组件展示。通过示例,展示了这两种组件的实现方法及其在实际开发中的应用价值。
63 1
|
4月前
|
缓存 前端开发 JavaScript
前端的全栈之路Meteor篇(二):容器化开发环境下的meteor工程架构解析
本文详细介绍了使用Docker创建Meteor项目的准备工作与步骤,解析了容器化Meteor项目的目录结构,包括工程准备、环境配置、容器启动及项目架构分析。提供了最佳实践建议,适合初学者参考学习。项目代码已托管至GitCode,方便读者实践与交流。
|
3月前
|
机器学习/深度学习 自然语言处理 数据管理
GraphRAG核心组件解析:图结构与检索增强生成
【10月更文挑战第28天】在当今数据科学领域,自然语言处理(NLP)和图数据管理技术的发展日新月异。GraphRAG(Graph Retrieval-Augmented Generation)作为一种结合了图结构和检索增强生成的创新方法,已经在多个应用场景中展现出巨大的潜力。作为一名数据科学家,我对GraphRAG的核心组件进行了深入研究,并在此分享我的理解和实践经验。
136 0

推荐镜像

更多