Spring上下文ContextLoaderListener作用
1·ContextLoaderListener 用法
ContextLoaderListener監聽器的作用就是啟動Web容器時,自動裝配ApplicationContext的配置資訊。因為它實現了ServletContextListener這個介面,在web.xml配置這個監聽器,啟 動容器時,就會預設執行它實現的方法。
至於ApplicationContext.xml這個配置檔案部署在哪,如何配置多個xml檔案,書上都沒怎麼詳 細說明。現在的方法就是檢視它的API文件。在ContextLoaderListener中關聯了ContextLoader這個類,所以整個載入配置 過程由ContextLoader來完成。看看它的API說明。
第一段說明ContextLoader可以由 ContextLoaderListener和ContextLoaderServlet生成。如果檢視ContextLoaderServlet的 API,可以看到它也關聯了ContextLoader這個類而且它實現了HttpServlet這個介面。
第二段,ContextLoader建立的是 XmlWebApplicationContext這樣一個類,它實現的介面是 WebApplicationContext->ConfigurableWebApplicationContext->ApplicationContext->BeanFactory 這樣一來spring中的所有bean都由這個類來建立
第三段,講如何部署applicationContext的xml檔案。
如果在web.xml中不寫任何引數配置資訊,預設的路徑是/WEB-INF/applicationContext.xml,在WEB-INF目錄下建立的xml檔案的名稱必須是applicationContext.xml;
如果是要自定義檔名可以在web.xml里加入contextConfigLocation這個context引數:
<context-param>
<param-name>contextConfigLocation</param-name>
<param -value>
/WEB-INF/classes/applicationContext-*.xml
</param-value>
</context-param>
在 裡指定相應的xml檔名,如果有多個xml檔案,可以寫在一起並一“,”號分隔。上面的 applicationContext-*.xml採用萬用字元,
比如這那個目錄下有applicationContext-ibatis- base.xml,applicationContext-action.xml,applicationContext-ibatis-dao.xml 等檔案,都會一同被載入。
由此可見applicationContext.xml的檔案位置就可以有兩種預設實現:
第一種:直接將之放到/WEB-INF下,之在web.xml中宣告一個listener;
第二種:將之放到classpath下,但是此時要在web.xml中加入,用它來指明你的 applicationContext.xml的位置以供web容器來載入。按照Struts2 整合spring的官方給出的檔案,寫成:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext-*.xml,classpath*:applicationContext-*.xml</param-value>
</context-param>
2·initWebApplicationContext作用
ApplicationContext是Spring的核心,Context我們通常解釋為上下文環境,我想用“容器”來表述它更容易理解一些,ApplicationContext則是“應用的容器”了;在Web應用中,
我們會用到WebApplicationContext,WebApplicationContext繼承自ApplicationContext;WebApplicationContext的初始化方式和BeanFactory.ApplicationContext有所區別,因為WebApplicationContext需要ServletContext例項,
也就是說它必須擁有Web容器的前提下才能完成啟動的工作.有過Web開發經驗的讀者都知道可以在web.xml中配置自啟動的Servlet或定義Web容器監聽器(ServletContextListener),藉助著兩者中的任何一個,我們就可以啟動Spring Web應用上下文的工作.
Spring分別提供了用於啟動WebApplicationContext的Servlet和Web容器監聽器:
org.springframework.web.context.ContextLoaderServlet;
org.springframework.web.context.ContextLoaderListener.
這兩個方法都是在web應用啟動的時候來初始化WebApplicationContext,我個人認為Listerner要比Servlet更好一些,因為Listerner監聽應用的啟動和結束,而Servlet得啟動要稍微延遲一些,如果在這時要做一些業務的操作,啟動的前後順序是有影響的。
配置例子如下:
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>
那麼在ContextLoaderListener和ContextLoaderServlet中到底做了什麼呢?
以ContextLoaderListener為例,我們可以看到
public void contextInitialized(ServletContextEvent event) {
this.contextLoader = createContextLoader();
this.contextLoader.initWebApplicationContext(event.getServletContext());
}
protected ContextLoader createContextLoader() {
return new ContextLoader();
}
ContextLoader是一個工具類,用來初始化WebApplicationContext,其主要方法就是initWebApplicationContext,我們繼續追蹤initWebApplicationContext這個方法(具體程式碼我不貼出,大家可以看Spring中的原始碼),
我們發現,原來ContextLoader是把WebApplicationContext(XmlWebApplicationContext是預設實現類)放在了ServletContext中,ServletContext也是一個“容器”,也是一個類似Map的結構,
而WebApplicationContext在ServletContext中的KEY就是WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,我們如果要使用WebApplicationContext則需要從ServletContext取出,
Spring提供了一個WebApplicationContextUtils類,可以方便的取出WebApplicationContext,只要把ServletContext傳入就可以了。
ApplicationContext 我們一般都是幹這個用的
ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
ProductMng productMng = (ProductMng)ctx.getBean("productMng");