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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

其中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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

如果不这样子分别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 Boot:ClassLoader的继承关系和影响

    前言 对spring boot本身启动原理的分析,请参考:http://hengyunabc.github.io/spring-boot-application-start-analysis/ Spr ...

  2. 浅谈Spring MVC知识

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

  3. 也谈Spring MVC

    在说Spring MVC之前,我们先说说没有Spring MVC的时候. 1)最早的Java Web程序,我们使用Servlet来处理请求,一般来说,一个请求对应一个Servlet,比如/user/a ...

  4. Spring MVC注解故障追踪记

    2019独角兽企业重金招聘Python工程师标准>>> Spring MVC是美团点评很多团队使用的Web框架.在基于Spring MVC的项目里,注解的使用几乎遍布在项目中的各个模 ...

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

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

  6. Spring mvc 上下文初始化过程

    为什么80%的码农都做不了架构师?>>>    在软件开发的中,如果某些特性的使用比较普遍,那么这些特性往往可以作为平台特性来实现,通过对这些平台特性进行有效的封装,使其向其他应用开 ...

  7. java架构-Spring MVC 与 Servlet

    相信大家都能够在上网上看到Spring MVC的核心类其实就是DispatherServlet,也就是Spring MVC处理请求的核心分发器.其实核心分发器几乎是所有MVC框架设计中的核心概念,像在 ...

  8. Spring MVC 到 Spring BOOT 的简化之路

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 来源:juejin.im/post/5aa22d1f5188255 ...

  9. Spring MVC-使用Spring Tool Suite IDE搭建Spring MVC开发环境

    Spring MVC 概述 新建Spring MVC Project 分析IDE建立的工程 Maven dependencies configuration Spring MVC configurat ...

最新文章

  1. 零拷贝、mmap、sendfile
  2. 用户权限sudo、suid、sgid以及facl等
  3. Elasticsearch 数据写入原理
  4. DS4800 用串口登陆0.1改成85状态
  5. fail树(bzoj 3172: [Tjoi2013]单词)
  6. 计算机音乐东京不太热,洛天依 - 东京不太热[FLAC格式]
  7. Python TCP接收/发送信息
  8. 云计算导论第二章习题总结
  9. WebRTC 音视频同步分析
  10. 两岸开源社群面面观(总结篇)
  11. 电商系统-提交订单并发处理
  12. python-numpy-pandas
  13. 2021 Macbook Pro 14 频繁问题回答
  14. 使用ROSE寻找超级增强子
  15. 简单响应式Bootstrap框架中文官网页面模板
  16. linux系统安装时无线键盘吗,[操作系统]用无线键盘鼠标装多系统或者装红旗LINUX4.0的朋友们进...
  17. 算术位移和逻辑位移(一篇懂)
  18. FastApi路径参数Query参数及参数类型
  19. 赶紧换掉windows系统自带记事本
  20. C++primer(第五版)习题答案

热门文章

  1. Android 获取系统或SDCARD剩余空间信息
  2. Win2003用NAT实现ADSL共享与×××服务器
  3. mybatis3+struts2+oracle整合的一个好的demo
  4. C#网页数据采集(三)HttpWebRequest
  5. 项目展示文案生成设计
  6. Xamarin.Forms探索--使用 Xamarin.Forms 来创建跨平台的用户界面
  7. ASP.NET 实现站内信功能(点对点发送,管理员群发)
  8. Java中文编码小结
  9. 朋友开网店 做个抓取数据的小程序
  10. 苹果手机如何恢复联系人呢?快速的恢复