欢迎访问昆山宝鼎软件有限公司网站! 设为首页 | 网站地图 | XML | RSS订阅 | 宝鼎邮箱 | 宝鼎售后问题提交 | 后台管理


新闻资讯

MENU

软件开发知识

一劳永逸的解决办法:bean都由ro 劳务派遣管理系统 ot WebApplicationContext加载 在一次配

点击: 次  来源:宝鼎软件 时间:2017-07-30

原文出处: hengyunabc

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则不能注入chile 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就没有处理惩罚到。假如在chile 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中初始化。