spring mvc里的root/child WebApplicationContext的继承关系

在传统的spring mvc程序里会有两个WebApplicationContext,一个是parent,从applicationContext.xml里加载的,一个是child,从servlet-context.xml里加载的。 
两者是继承关系,child WebApplicationContext 可以通过getParent()函数获取到root WebApplicationContext。

简单地说child WebApplicationContext里的bean可以注入root WebApplicationContext里的bean,而parent WebApplicationContext的bean则不能注入child WebApplicationContext里的bean。

一个典型的web.xml的内容是:

    <!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:/applicationContext.xml</param-value>
</context-param> <!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener> <!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet> <servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

其中root WebApplicationContext是通过listener初始化的,child WebApplicationContext是通过servlet初始化的。

而在applicationContext.xml里通常只component-scan非Controller的类,如:

    <context:component-scan base-package="io.github.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>

servlet-context.xml里通常只component-scan Controller类,如:

    <context:component-scan base-package="io.github.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>

如果不这样子分别component-scan的话,可能会出现Bean重复初始化的问题。

上面是Spring官方开始时推荐的做法。

root/child WebApplicationContext继承关系带来的麻烦

root WebApplicationContext里的bean可以在不同的child WebApplicationContext里共享,而不同的child WebApplicationContext里的bean区不干扰,这个本来是个很好的设计。

但是实际上有会不少的问题: 
* 不少开发者不知道Spring mvc里分有两个WebApplicationContext,导致各种重复构造bean,各种bean无法注入的问题。 
* 有一些bean,比如全局的aop处理的类,如果先root WebApplicationContext里初始化了,那么child WebApplicationContext里的初始化的bean就没有处理到。如果在child WebApplicationContext里初始化,在root WebApplicationContext里的类就没有办法注入了。 
* 区分哪些bean放在root/child很麻烦,不小心容易搞错,而且费心思。

一劳永逸的解决办法:bean都由root WebApplicationContext加载

在一次配置metrics-spring时,对配置@EnableMetrics配置在哪个WebApplicationContext里,感到很蛋疼。最终决定试下把所有的bean,包括Controller都移到root WebApplicationContext,即applicationContext.xml里加载,而servlet-context.xml里基本是空的。结果发现程序运行完全没问题。

后面在网上搜索了下,发现有一些相关的讨论:

http://forum.spring.io/forum/spring-projects/container/89149-servlet-context-vs-application-context

spring boot里的做法

在spring boot里默认情况下不需要component-scan的配置,于是猜测在Spring boot里是不是只有一个WebApplicationContext?

后面测试下了,发现在spring boot里默认情况下的确是只有一个WebApplicationContext:org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext,所以在spring boot里省事了很多。

总结

spring 的ApplicationContext继承机制是一个很好的设计,在很多其它地方都可以看到类似的思路,比如Java的class loader。但是在大部分spring web程序里,实际上只要一个WebApplicationContext就够了。如果分开rott/child WebApplicationContext会导致混乱,而没什么用。

所以推荐把所有的Service/Controller都移到root WebApplicationContext中初始化。

http://blog.csdn.net/hengyunabc/article/details/47072637

扯谈spring mvc之WebApplicationContext的继承关系的更多相关文章

  1. Spring☞WebApplicationContext的继承关系

    spring mvc里的root/child WebApplicationContext的继承关系 在传统的spring mvc程序里会有两个WebApplicationContext,一个是pare ...

  2. Spring MVC 了解WebApplicationContext中特殊的bean类型

    Spring MVC 了解WebApplicationContext中特殊的bean类型 Spring的DispatcherServlet使用了特殊的bean来处理请求.渲染视图等,这些特定的bean ...

  3. 深入Spring Boot:ClassLoader的继承关系和影响

    前言 对spring boot本身启动原理的分析, Spring boot里的ClassLoader继承关系 可以运行下面提供的demo,分别在不同的场景下运行,可以知道不同场景下的Spring bo ...

  4. 浅谈Spring MVC知识

    关于MVC框架,我相信大家都不陌生,都会说也就是模型-视图-控制器这三层的框架结构,如果你参加面试的时候考官会问:“MVC框架是什么?你说一说.”其实我们都知道这个问题还需要问的,只要你是一个开发人员 ...

  5. Spring MVC学习------------WebApplicationContext

    父子上下文(WebApplicationContext) 假设你使用了listener监听器来载入配置.一般在Struts+Spring+Hibernate的项目中都是使用listener监听器的. ...

  6. 深入分析Spring 与 Spring MVC容器

    1 Spring MVC WEB配置 Spring Framework本身没有Web功能,Spring MVC使用WebApplicationContext类扩展ApplicationContext, ...

  7. spring mvc DispatcherServlet详解之前传---FrameworkServlet

    做项目时碰到Controller不能使用aop进行拦截,从网上搜索得知:使用spring mvc 启动了两个context:applicationContext 和WebapplicationCont ...

  8. Spring mvc web 配置

    Spring Framework本身没有Web功能, Spring MVC使用WebApplicationContext类扩展ApplicationContext ,使得拥有web功能.那么,Spri ...

  9. 深入分析Spring 与 Spring MVC容器(山东数漫江湖)

    1 Spring MVC WEB配置 Spring Framework本身没有Web功能,Spring MVC使用WebApplicationContext类扩展ApplicationContext, ...

随机推荐

  1. iOS中UITableView的cell点击事件不触发didSelectRowAtIndexPath(汇总)

    iOS中UITableView的cell点击事件不触发didSelectRowAtIndexPath 首先分析有几种原因,以及相应的解决方法 1.UITableViewCell的userInterac ...

  2. mysql group by的用法 注意

    group by 用法: 官方的解释:select 后面的字段必须出现在 group by 后面, 除非是聚合,sum,或者count 但是如果 是多表联查, SELECT    c.`name` A ...

  3. 【asp.net爬虫】asp.NET分页控件抓取第n页数据 javascript:__doPostBack

    最近在模拟HTTP请求抓取数据,但是服务器是asp.net开发的 分页控件代码 <tr> <td align="left">共&nbsp210&am ...

  4. PHP中统计目录中文件以及目录中目录的大小

    <?php  #循环遍历目录中所有的文件,并统计目录和文件的大小  $dirName="phpMyAdmin";  $dir=opendir($dirName);  #返回一 ...

  5. [Angular 2] Inject Service

    TypeScript is used heavily as we build up our application, but TypeScript isn’t required. If you wan ...

  6. Linux的进程优先级-邹立巍

    http://liwei.life/2016/04/07/linux%E7%9A%84%E8%BF%9B%E7%A8%8B%E4%BC%98%E5%85%88%E7%BA%A7/

  7. Qt 学习之路 :Qt 线程相关类

    希望上一章有关事件循环的内容还没有把你绕晕.本章将重新回到有关线程的相关内容上面来.在前面的章节我们了解了有关QThread类的简单使用.不过,Qt 提供的有关线程的类可不那么简单,否则的话我们也没必 ...

  8. Linux磁盘管理:LVM逻辑卷的拉伸及缩减

    ①查看当前VG的信息,保证VG中有足够的空闲空间 通过 vgdisplay 或者 vgs 命令 [root@rusky ~]# vgs rusky-vg VG #PV #LV #SN Attr VSi ...

  9. 如何做高大上的网站布局 -------------------->>转至(卧牛SEO/武汉SEO http://blog.sina.com.cn/zhengkangseo )

    SEO开始做,最重要的是网站布局,一个网站布局决定了用户在网站的停留时间,在网站中放入用户想要的内容之外,更重要的是要让用户看到网站之后,一目了然,视觉和感官上良好的体验.那新手该如何做网站布局呢? ...

  10. bootstrap的流式布局

    Bootstrap---Fluid layout 流布局 流布局是一种适应屏幕的做法.即不固定块的宽度,而是采用百分比作为单位来确定每一块的宽度.这种布局非常适合一次编写,然后自适应各种不同大小的屏幕 ...