標籤:io ar sp java 檔案 資料 on art 問題
在Web容器(比如Tomcat)中配置Spring時,你可能已經司空見慣於web.xml檔案中的以下配置代碼:
<context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml</param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <servlet> <servlet-name>mvc-dispatcher</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>mvc-dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
以上配置首先會在ContextLoaderListener中通過<context-param>中的applicationContext.xml建立一個ApplicationContext,再將這個ApplicationContext塞到ServletContext裡面,通過ServletContext的setAttribute方法達到此目的,在ContextLoaderListener的原始碼中,我們可以看到這樣的代碼:
servletContext.setAttribute( WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
以上由ContextLoaderListener建立的ApplicationContext是共用於整個Web應用程式的,而你可能早已經知道,DispatcherServlet會維持一個自己的ApplicationContext,預設會讀取/WEB-INFO/<dispatcherServletName>-servlet.xml檔案,而我麼也可以重新設定:
<servlet> <servlet-name> customConfiguredDispacherServlet </servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <init-param> <param-name> contextConfigLocation </param-name> <param-value> /WEB-INF/dispacherServletContext.xml </param-value> </init-param> <load-on-startup>1</load-on-startup></servlet>
問題是:以上兩個ApplicationContext的關係是什麼,它們的作用作用範圍分別是什麼,它們的用途分別是什嗎?
ContextLoaderListener中建立ApplicationContext主要用於整個Web應用程式需要共用的一些組件,比如DAO,資料庫的ConnectionFactory等。而由DispatcherServlet建立的ApplicationContext主要用於和該Servlet相關的一些組件,比如Controller、ViewResovler等。
對於作用範圍而言,在DispatcherServlet中可以引用由ContextLoaderListener所建立的ApplicationContext,而反過來不行。
在Spring的具體實現上,這兩個ApplicationContext都是通過ServletContext的setAttribute方法放到ServletContext中的。但是,ContextLoaderListener會先於DispatcherServlet建立ApplicationContext,DispatcherServlet在建立ApplicationContext時會先找到由ContextLoaderListener所建立的ApplicationContext,再將後者的ApplicationContext作為參數傳給DispatcherServlet的ApplicationContext的setParent()方法,在Spring原始碼中,你可以在FrameServlet.java中找到如下代碼:
wac.setParent(parent);
其中,wac即為由DisptcherServlet建立的ApplicationContext,而parent則為有ContextLoaderListener建立的ApplicationContext。此後,架構又會調用ServletContext的setAttribute()方法將wac加入到ServletContext中。
當Spring在執行ApplicationContext的getBean時,如果在自己context中找不到對應的bean,則會在父ApplicationContext中去找。這也解釋了為什麼我們可以在DispatcherServlet中擷取到由ContextLoaderListener對應的ApplicationContext中的bean。
Spring: DispacherServlet和ContextLoaderListener中的WebApplicationContext的關係