扯谈spring mvc之WebApplicationContext的继承关系
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的继承关系相关推荐
- 深入Spring Boot:ClassLoader的继承关系和影响
前言 对spring boot本身启动原理的分析,请参考:http://hengyunabc.github.io/spring-boot-application-start-analysis/ Spr ...
- 浅谈Spring MVC知识
关于MVC框架,我相信大家都不陌生,都会说也就是模型-视图-控制器这三层的框架结构,如果你参加面试的时候考官会问:"MVC框架是什么?你说一说."其实我们都知道这个问题还需要问的, ...
- 也谈Spring MVC
在说Spring MVC之前,我们先说说没有Spring MVC的时候. 1)最早的Java Web程序,我们使用Servlet来处理请求,一般来说,一个请求对应一个Servlet,比如/user/a ...
- Spring MVC注解故障追踪记
2019独角兽企业重金招聘Python工程师标准>>> Spring MVC是美团点评很多团队使用的Web框架.在基于Spring MVC的项目里,注解的使用几乎遍布在项目中的各个模 ...
- spring mvc DispatcherServlet详解之前传---FrameworkServlet
做项目时碰到Controller不能使用aop进行拦截,从网上搜索得知:使用spring mvc 启动了两个context:applicationContext 和WebapplicationCont ...
- Spring mvc 上下文初始化过程
为什么80%的码农都做不了架构师?>>> 在软件开发的中,如果某些特性的使用比较普遍,那么这些特性往往可以作为平台特性来实现,通过对这些平台特性进行有效的封装,使其向其他应用开 ...
- java架构-Spring MVC 与 Servlet
相信大家都能够在上网上看到Spring MVC的核心类其实就是DispatherServlet,也就是Spring MVC处理请求的核心分发器.其实核心分发器几乎是所有MVC框架设计中的核心概念,像在 ...
- Spring MVC 到 Spring BOOT 的简化之路
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 来源:juejin.im/post/5aa22d1f5188255 ...
- Spring MVC-使用Spring Tool Suite IDE搭建Spring MVC开发环境
Spring MVC 概述 新建Spring MVC Project 分析IDE建立的工程 Maven dependencies configuration Spring MVC configurat ...
最新文章
- 零拷贝、mmap、sendfile
- 用户权限sudo、suid、sgid以及facl等
- Elasticsearch 数据写入原理
- DS4800 用串口登陆0.1改成85状态
- fail树(bzoj 3172: [Tjoi2013]单词)
- 计算机音乐东京不太热,洛天依 - 东京不太热[FLAC格式]
- Python TCP接收/发送信息
- 云计算导论第二章习题总结
- WebRTC 音视频同步分析
- 两岸开源社群面面观(总结篇)
- 电商系统-提交订单并发处理
- python-numpy-pandas
- 2021 Macbook Pro 14 频繁问题回答
- 使用ROSE寻找超级增强子
- 简单响应式Bootstrap框架中文官网页面模板
- linux系统安装时无线键盘吗,[操作系统]用无线键盘鼠标装多系统或者装红旗LINUX4.0的朋友们进...
- 算术位移和逻辑位移(一篇懂)
- FastApi路径参数Query参数及参数类型
- 赶紧换掉windows系统自带记事本
- C++primer(第五版)习题答案