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

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 解析 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,后续会有更多实战、源码、架构干货分享!

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

目录
相关文章
|
3天前
|
移动开发 前端开发 HTML5
Twaver-HTML5基础学习(20)数据容器(3)_数据的批量加载(节省性能方法)
本文介绍了Twaver HTML5中数据的批量加载方法,通过使用`box.startBatch()`可以在大量数据加载时提高性能。文章通过示例代码展示了如何在React组件中使用批量加载功能,以减少界面重绘次数并提升效率。
19 1
Twaver-HTML5基础学习(20)数据容器(3)_数据的批量加载(节省性能方法)
|
9天前
|
负载均衡 5G 网络性能优化
深入解析LTE(长期演进技术)的基本架构及其关键组件
深入解析LTE(长期演进技术)的基本架构及其关键组件
54 2
|
29天前
|
监控 网络协议 Java
Tomcat源码解析】整体架构组成及核心组件
Tomcat,原名Catalina,是一款优雅轻盈的Web服务器,自4.x版本起扩展了JSP、EL等功能,超越了单纯的Servlet容器范畴。Servlet是Sun公司为Java编程Web应用制定的规范,Tomcat作为Servlet容器,负责构建Request与Response对象,并执行业务逻辑。
Tomcat源码解析】整体架构组成及核心组件
|
30天前
|
Kubernetes API 调度
Kubernetes 架构解析:理解其核心组件
【8月更文第29天】Kubernetes(简称 K8s)是一个开源的容器编排系统,用于自动化部署、扩展和管理容器化应用。它提供了一个可移植、可扩展的环境来运行分布式系统。本文将深入探讨 Kubernetes 的架构设计,包括其核心组件如何协同工作以实现这些功能。
83 0
|
7天前
|
Linux iOS开发 Docker
Docker:容器化技术的领航者 —— 从基础到实践的全面解析
在云计算与微服务架构日益盛行的今天,Docker作为容器化技术的佼佼者,正引领着一场软件开发与部署的革命。它不仅极大地提升了应用部署的灵活性与效率,还为持续集成/持续部署(CI/CD)提供了强有力的支撑。
176 69
|
18天前
|
开发工具
Flutter-AnimatedWidget组件源码解析
Flutter-AnimatedWidget组件源码解析
|
5天前
|
存储 开发框架 数据可视化
深入解析Android应用开发中的四大核心组件
本文将探讨Android开发中的四大核心组件——Activity、Service、BroadcastReceiver和ContentProvider。我们将深入了解每个组件的定义、作用、使用方法及它们之间的交互方式,以帮助开发者更好地理解和应用这些组件,提升Android应用开发的能力和效率。
|
1月前
|
存储 安全 虚拟化
深入解析:Docker的架构与组件
【8月更文挑战第27天】
123 5
|
28天前
|
监控 安全 网络安全
|
28天前
|
前端开发 UED 开发者
React组件优化全攻略:深度解析让你的前端应用飞速运行的秘诀——从PureComponent到React.memo的彻底性能比较
【8月更文挑战第31天】在构建现代Web应用时,性能是提升用户体验的关键因素。React作为主流前端库,其组件优化尤为重要。本文深入探讨了React组件优化策略,包括使用`PureComponent`、`React.memo`及避免不必要的渲染等方法,帮助开发者显著提升应用性能。通过实践案例对比优化前后效果,不仅提高了页面渲染速度,还增强了用户体验。优化React组件是每个开发者必须关注的重点。
45 0

热门文章

最新文章

推荐镜像

更多