扯談spring mvc之WebApplicationContext的繼承關係

來源:互聯網
上載者:User

標籤:網上   location   pps   ade   shared   傳統   https   map   embed   

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非常麻煩。不小心easy搞錯,並且費心思。

一勞永逸的解決的方法: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中初始化。

扯談spring mvc之WebApplicationContext的繼承關係

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.