Spring | xx-servlet.xml 和 applicationContext.xml 的區別

kycool 發表於 2021-10-23
Spring

applicationContext.xmlxx-servlet.xml 是兩個具有父子關係的上下文配置。

1 定義不同

1.1 applicationContext.xml

  • 顧名思義,應用上下文配置,定義了應用整體的上下文配置,這些上下文貫穿於整個應用,應用級別的配置。
  • 多個 servlet 可以共享此配置

web.xml 中配置如下:

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

ContextLoaderListenerSpring 的監聽器,它的作用就是啟動 Web 容器時,自動裝配 ApplicationContext 的配置資訊。因為它實現了 ServletContextListener 這個介面,在 web.xml 配置這個監聽器,啟動容器時,就會預設執行它實現的方法。

1.2 xx-servlet.xml

  • servlet 級別的配置,可以獨立多個配置檔案,一個應用中可以配置多個 servlet
  • 通常用於載入 controller 層需要的類,比如攔截器, mvc 標籤載入的類

web.xml 中配置如下:

    <servlet>
        <servlet-name>spring3</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring3-servlet.xml</param-value>
        </init-param>
        <load-on-startup>3</load-on-startup>
    </servlet>

通過配置即可瞭解,spring3-servlet.xml 其實就是指定的 org.springframework.web.servlet.DispatcherServlet 對應的配置。

2 關係等級

Spring lets you define multiple contexts in a parent-child hierarchy.  
  The applicationContext.xml defines the beans for the "root webapp context", i.e. the context associated with the webapp.  
  The spring-servlet.xml (or whatever else you call it) defines the beans for one servlet's app context. 
There can be many of these in a webapp, one per Spring servlet (e.g. spring1-servlet.xml for servlet spring1, spring2-servlet.xml 
for servlet spring2).  
  Beans in spring-servlet.xml can reference beans in applicationContext.xml, but not vice versa.  
  All Spring MVC controllers must go in the spring-servlet.xml context.  
  In most simple cases, the applicationContext.xml context is unnecessary. It is generally used to contain beans that are shared 
between all servlets in a webapp. If you only have one servlet, then there's not really much point, unless you have a specific use for it.

通過官方文件的說明,即可以瞭解,這兩者是具有父子關係

配置關係
applicationContext.xml父親
xx-servlet.xml兒子

要點:

  • 一個 bean 如果在兩個檔案中都被定義了(比如兩個檔案中都定義了 component scan 掃描相同的 package ), spring 會在 application contextservlet context 中都生成一個例項,他們處於不同的上下文空間中,他們的行為方式是有可能不一樣的。
  • 如果 application contextservlet context 中都存在同一個 @Service 的例項,controller(在 servlet context 中) 通過 @Resource 引用時, 會優先選擇 servlet context 中的例項。
  • servlet context 可以引用 application context 裡的例項,反之不可以
  • 多個 servlet 共享 application context 裡的例項
  • applicationContextxx-servlet 定義的 bean 最好不要重複,xx-servlet t最好只掃描 @controlerapplicationContext 掃描其它。

例如:

applicationContext.xml

<context:component-scan base-package="com.test" use-default-filters="true">
  <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>

xx-servlet.xml

<context:component-scan base-package="com.test.controller" use-default-filters="false">
  <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>

注意:

  • use-default-filters 用來指示是否自動掃描帶有 @Component@Repository@Service@Controller 的類。預設為 true,即預設掃描
  • <context:include-filter/> 子標籤是用來新增掃描註解
  • <context:exclude-filter/> 子標籤是用來排除掃描註解