SpringMVC的应用上下文管理

如何加载spring mvc

对于基于servlet的web容器来说,遵循的是servlet规范,入口配置文件是web.xml。这类web容器会在启动的时候会而且仅会加载如下三种类型的对象:

1. context listener
2. filter
3. servlet

而且有一定的加载和销毁顺序!创建时一般就是按照上面序号所示的顺序,至于统一类型的对象比如servlet则按照在web.xml定义的顺序进行加载。

基于此,一个使用spring mvc简单的web.xml配置如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<web-app  version="3.1" 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_3_1.xsd">

     <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
        <!-- 默认是/WEB-INF/applicationContext.xml -->
     </context-param>

     <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
     </listener>

    <servlet>
        <servlet-name>SpringMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/SpringMVC-servlet.xml</param-value>
            <!-- 默认是/WEB-INF/[servlet名字]-servlet.xml -->
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>SpringMVC</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>

为什么需要加载ContextLoaderListener和DispatcherServlet

DispatcherServlet
  • DispatcherServlet是Spring前端控制器的实现,用以转发、匹配、处理每个servlet请求。
  • DispatcherServlet默认使用WebApplicationContext作为上下文,默认加载/WEB-INF/[server-name]-servlet.xml
ContextLoaderListener

用于加载Spring的上下文,默认加载/WEB-INF/applicationContext.xml

为什么同时使用两种上下文

因为两者作用不同,DispatcherServlet上下文仅负责MVC相关bean的配置管理(如ViewResolver、Controller、MultipartResolver等),ContextLoaderListener上下文则负责整个spring相关bean的配置管理(如相关Service、DAO等)。

关联
  • ContextLoaderListener加载的上下文放在ServletContext的key为WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE属性中,ContextLoaderListener初始化的上下文加载的Bean是对于整个应用程序共享的
  • DispatcherServlet在建立自己的IoC上下文时,会利用WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE先从ServletContext中获取之前的根上下文(即WebApplicationContext)作为自己上下文的parent上下文。有了这个parent上下文之后,再初始化自己持有的上下文。加载的上下文在每次请求时会放一份在request对象的key为WEB_APPLICATION_CONTEXT_ATTRIBUTE属性中
  • 当Spring在执行ApplicationContext的getBean时, 如果在自己context中找不到对应的bean,则会在父ApplicationContext中去找 。这也解释了为什么我们可以在DispatcherServlet中获取到由ContextLoaderListener对应的ApplicationContext中的bean。
相关问题
描述

因为有至少连个上下文,同一个Bean可能会被加载两次,造成不必要的资源浪费

原因

ContextLoaderListener和DispatcherServlet的配置文件都加载了同一个Bean

解决措施

讲Bean的定义只放在一个配置文件里,让另一个配置文件为空
如果是扫描,则通过过滤语法排除

比如spring-servet.xml

<mvc:annotation-driven />
    <!-- Scans for annotated @Controllers in the classpath -->
    <context:component-scan base-package="xx.yy" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan

这样子,就表明只扫描@Controller注解的Bean.注意这里的user-default-filters=”false”

参考

深入分析Spring 与 Spring MVC容器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值