Spring当中ContextLoaderListener和DispatcherServlet所加载的context的关系

一.写在前面

上次的ServletContext与WebApplicationContext一文只是梳理清楚ServletContext和由ContextLoaderListener加载的WebApplicationContext的关系,今天再来梳理一下
ContextLoaderListener加载的WebApplicationContext和DispatcherServlet加载的applicationContext是spring MVC的上下文的关系

二.二者关系

1.ContextLoaderListener所加载的context
被spring通过servletContext.setAttribute(WebApplicationContext.
ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context)
存放到ServletContext的attribute中。
该上下文可通过
WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext)或WebApplicationContextUtils.getWebApplicationContext(servletContext)
方法来获取

2.DispatcherServlet加载context完成后,如果publishContext属性的值设置为true的话(缺省为true) 
会将context存放在ServletContext的key为org.springframework.web.servlet.
FrameworkServlet.CONTEXT. + (servletName)的attribute中。

xml配置如下:
<servlet>  
    <servlet-name>dispatcher</servlet-name>  
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
    <init-param>  
    <param-name>contextConfigLocation</param-name>  
    <param-value>classpath*:dispatcher-servlet.xml</param-value>  
    </init-param>  
</servlet>

DispatcherServlet所加载的applicationContext可以认为是mvc私有的context,
由于保存在servletContext中的key值与通过ContextLoaderListener加载进来的applicationContext使用的key值不相同,
因此如果只使用DispatcherServlet加载context的话,如果程序中有地方使用WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext) 
来试图获取applicationContext时,就会抛出”No WebApplicationContext found: no ContextLoaderListener registered?”的exception。

三.注意

Spring的ContextLoaderListener所创建出来的context和Spring MVC DispatcherServlet所创建出来的context
是父子关系,FrameworkServlet在实例化对应的applicationContext后通过setParent
将从ServletContext中获取到的ContextLoaderListener创建的applicaitonContext设置成父上下文,
然后加载在对应的xml配置文件对其初始化。

father WebApplicationContext里的bean可以被注入到child WebApplicationContext里的bean,
而child WebApplicationContext的bean则不能被注入到parent WebApplicationContext里的bean。
所以在使用Spring MVC时启用自动检测功能,应在applicationContext.xml里只component-scan非Controller的类,
而在Spring MVC里只component-scan Controller类

applicationContext.xml配置如下
<context:component-scan base-package="com.test">
   <context:exclude-filter  expression="org.springframework.stereotype.Controller" type="annotation" />
   <context:exclude-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice" />
</context:component-scan>

dispatcher-servlet.xml的配置如下
<context:component-scan base-package="com.test.web" use-default-filters="false">
    <context:include-filter expression="org.springframework.stereotype.Controller"
        type="annotation" />
    <context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice" />
</context:component-scan>

虽然这两个context上下文是一对父子关系,但它们加载的bean不是合并存储的,所以个人建议,
基于mvc相关的spring配置由DispatcherServlet加载,而其余的JavaBean都交给ContextLoaderListener加载

 

转载于:https://my.oschina.net/st9/blog/1619495

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值