5

相对于spring boot我们使用spring mvc更加频繁和熟悉。sprint boot具有spring mvc的功能,两者之间到底存在着什么样的关系,通过下面的篇幅我们一起来分析。

我们再回顾下spring mvc的配置,首先看下web.xml:

图片描述

可以看到该文件中配置了context-param、listener以及servlet信息
(执行顺序:context-param -> listener -> filter -> servlet)
spring-servlet.xml是应用初始化容器所使用的配置。

ContextLoaderListener:在启动Web容器时,自动装配Spring applicationContext.xml的配置信息,本质上是创建了一个WebApplicationContext,也就是创建了spring ioc容器,当然也可以不配置该listener,也就无法使用其ioc提供的功能;正常情况下,都会配置。

ContextLoadListener结构如下:

图片描述

ContextLoaderListener实现了ServletContextListener,我们应该很熟悉了,有两个方法

  • contextInitialized(ServletContextEvent sce):All ServletContextListeners are notified of context initialization before any filter or servlet in the web application is initialized.
    即所有ServletContextListeners的该方法都会在filter和servlet初始化之前调用。

  • contextDestroyed (ServletContextEvent sce):All servlets and filters have been destroy()ed before any ServletContextListeners are notified of context destruction.
    即所有ServletContextListeners的该方法都会在filter和servlet销毁之前调用。

参数均为ServletContextEvent,可以获取ServletContext对象。

同时ContextLoaderListener继承自ContextLoader,监听器的核心功能都在此类中。
在ContextLoaderListener的contextInitialized方法中调用了父类ContextLoader的
initWebApplicationContext(ServletContext servletContext)方法,该方法的主要就是创建了一个IOC容器即WebApplicationContext,并将IOC容器存到servletContext中。

执行流程如下:

  1. createWebApplicationContext(servletContext)
    1).determineContextClass决定使用什么类型的容器
    先去web.xml中获取contextClass配置,获取到了就用配置的容器,如果没有指定IOC容器类型,默认为XmlWebApplicationContext。
    默认容器在spring-web的jar包中的配置文件ContextLoader.properties中配置:
    org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext。
    2).((ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass))
    创建IOC容器

  2. loadParentContext(servletContext)
    加载web.xml中的父容器信息,如果有则设置。父容器是不能够引用子容器中的bean,子类可以引用父容器中的bean,各个自容器中的bean互不可见。

  3. configureAndRefreshWebApplicationContext
    a.获取contextConfigLocation配置(applicationContext.xml)作为初始化容器的图纸,Spring工厂进行Bean生产、依赖关系注入(装配)及Bean实例分发都依赖于它。
    b.获取ApplicationContextInitializer的实现类
    ApplicationContextInitializer:主要目的就是在ConfigurableApplicationContext类型(或者子类型)的ApplicationContext做refresh之前,允许我们对ConfigurableApplicationContext的实例做进一步的设置或者处理。
    可以在web.xml中通过如下配置设置param-name
    globalInitializerClasses:代表所有的web application都会应用或
    contextInitializerClasses:代表只有当前的web application会使用
    配置如下:

    <context-param>
        <param-name>contextInitializerClasses</param-name>
        <param-value>com.my.MyApplicationContextInitializer</param-value>
    </context-param>

    所有实现类会在此处实例化并依次执行initialize方法。

  4. 将该IOC容器放到servletContext中

    图片描述

  5. 将当前线程类加载器和IOC容器做关联,以便于后续获取IOC容器
    Java的线程上下文类加载器请见文章 类加载器相关

上述过程中所涉及到的接口及类图如下:

图片描述

  • ApplicationContext:context的顶层类,ApplicationContext继承了BeanFactory,这也说明了 Spring 容器中运行的主体对象是 Bean,另外 ApplicationContext 继承了 ResourceLoader 接口,使得 ApplicationContext可以访问到任何外部资源。

  • ConfigurableApplicationContext:ConfigurableApplicationContext接口中定义了一些基本操作,比如设置上下文ID,设置父应用上下文,添加监听器和刷新容器相关的操作等。

  • ConfigurableWebApplicationContext:是web应用上下文使用的接口,主要是设置servletContext和servletConfig。

  • AbstractApplicationContext:实现refresh方法,构建Bean关系网,构建容器的核心方法。

至此:springmvc启动过程中第一大部分构建IOC容器部分结束


帅帅的波
193 声望12 粉丝