Spring+SpringMVC项目中的容器初始化过程

文章目录

容器初始化过程

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">

    <!--定义web应用的名称-->
    <display-name>ssmdemo</display-name>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/spring-context.xml</param-value>
    </context-param>

    <!-- Spring上下文监听器,用来加载Spring的上下文配置并初始化Spring -->
    <listener>
        <description>启动spring容器</description>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <!-- LOG4J上下文监听器,用来加载LOG4J2的配置并初始化LOG4J -->
    <listener>
        <listener-class>org.apache.logging.log4j.web.Log4jServletContextListener</listener-class>
    </listener>

    <!-- 字符编码过滤器,将编码改为UTF-8-->
    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    
    <!--对所有的请求都进行过滤-->
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!-- SpringMVC前置控制器,拦截匹配的请求,把拦截下来的请求,根据相应的规则分发到目标Controller来处理-->
    <servlet>
        <servlet-name>spring-mvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 指定路径SpringMVC上下文配置路径,也可以使用默认的规则,即:/WEB-INF/<servlet-name>-servlet.xml,如spring-mvc-servlet.xml-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring/spring-mvc.xml</param-value>
        </init-param>
        <!-- 随web应用启动而启动 -->
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>spring-mvc</servlet-name>
        <!--指定所有请求都通过DispatcherServlet来处理-->
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

初始化过程

  • Web服务器(如Tomcat)启动

  • Tomcat读取server.xml配置文件,加载里面配置的Web应用,为每个应用创建一个全局上下文环境ServletContext(ApplicationContextFacade);

  • Tomcat读取web.xml配置文件,开始按顺序加载(context-param、listener、filter、servlet);

  • 获取context-param节点信息,保存到ServletContext中(值为Spring配置文件的位置);

  • 获取listener节点信息,创建Listener实例集合(开始监听),其中的ContextLoaderListener监听器就是用来完成Spring容器初始化的。

  • ContextLoaderListener监听触发,完成Spring容器(XmlWebApplicationContext)的初始化;

    • 创建Spring容器,通过ServletContext.getinitialParameter("contextConfigLoaction")从ServletContext中获取Spring配置文件的位置;

    • 读取Spring配置文件信息,将相关Bean加载到Spring容器中。

  • Spring容器加载完成,将容器保存到ServletContext中;

    • Spring容器对象以org.springframework.web.context.WebApplicationContext.ROOT为key的key-value形式存入到ServletContext.context.attributes属性中。
  • 获取filter节点信息,创建Filter实例集合,保存到ServletContext中;

  • 获取servlet节点信息,创建Servlet实例集合,其中的DispatcherServlet就是用来完成SpringMVC容器(XmlWebApplicationContext)初始化的;

    • 根据servlet节点中的servlet-class创建相应的Servlet;

    • 其中DispatcherServlet的初始过程,进行SpringMVC容器初始化;

    • 读取该servlet节点中的SpringMVC配置文件信息,将相关Bean加载到SpringMVC容器中;

    • 设置Spring容器为SpringMVC容器的父容器。

      当执行SpringMVC容器的getBean方法在自己的context中找不到对应的bean,则会在父容器Spring容器的context中找对应的bean。

  • SpringMVC容器初始化完成,将容器保存到ServletContext中。

至此,SSM项目启动完成。

简单概括初始化过程

  • Web服务器启动
  • 加载Web应用
  • 创建ServletContext
  • 创建Listener,完成Spring容器初始化
  • 创建Filter
  • 创建Servlet,完成SpringMVC容器初始化

初始化流程图

Filter、Servlet等无法自动注入Bean

Listener、Filter、Servlet无法使用@Autowired自动装配bean。

并不是因为他们初始化的时候bean还没初始化。而是因为Listener、Filter、Servlet是Web容器管理的,而bean是Spring容器或SpringMVC容器管理的。Web容器根部就不认识@Autowired注解,当然不可能注入成功。

相关推荐
咖啡八杯1 小时前
GoF设计模式——解释器模式
java·后端·spring·设计模式
优橙教育1 小时前
5G网优培训 vs Java开发:转行选哪个?
java·开发语言·5g
掘金码甲哥1 小时前
这块终端神器, 必须吹爆!
后端
糖果店的幽灵2 小时前
【DeepAgents 从入门到精通】Context Management 上下文管理
java·人工智能·后端·spring·中间件·langgraph·deepagents
Csvn2 小时前
📊 SQL 入门 Day 8:集合操作 — 用 SQL 做数学里的"并交差"
后端·sql
腻害兔3 小时前
【若依项目-产品经理视角】RuoYi-Vue-Pro 源码拆解:字典、短信、邮件、通知——后台系统的“基础设施四件套“!
java·前端·vue.js·产品经理·ai编程
碎光拾影4 小时前
ARM交叉工具链各工具作用及IMX6ULL平台LED+蜂鸣器裸机程序实现
java·开发语言·数据库
Miao121314 小时前
微服务 API 测试实践:海外某民宿平台如何构建模式驱动测试基础设施
java·开发语言
腻害兔5 小时前
【若依项目-产品经理视角】RuoYi-Vue-Pro 源码拆解:支付模块 yudao-module-pay,一个让产品经理都看懂的支付中台设计
java·前端·vue.js·产品经理·ai编程
码事漫谈5 小时前
告别数据孤岛与AI“水土不服”:金仓多模融合时序库如何让数据真正服务于业务
后端