舉例:springweb-2 項目(在 spring-web 項目基礎上修改)
對于 Web 應用來說,ServletContext 對象是唯一的,一個 Web 應用,只有一個ServletContext 對象,該對象是在 Web 應用裝載時初始化的。若將 Spring 容器的創建時機,放在 ServletContext 初始化時,就可以保證 Spring 容器的創建只會執行一次,也就保證了Spring 容器在整個應用中的唯一性。
當 Spring 容器創建好后,在整個應用的生命周期過程中,Spring 容器應該是隨時可以被訪問的。即,Spring 容器應具有全局性。而放入 ServletContext 對象的屬性,就具有應用的全局性。所以,將創建好的 Spring 容器,以屬性的形式放入到 ServletContext 的空間中,就保證了 Spring 容器的全局性。
上述的這些工作,已經被封裝在了如下的 Spring 的 Jar 包的相關 API 中: spring-web-4.3.9.RELEASE
在Web項目中使用Spring,需要導入Spring對Web的支持包:spring-web-RELEASE。
該包在 Spring 框架的解壓目錄下的 libs 目錄中。
若要在ServletContext初始化時創建Spring容器,就需要使用監聽器接口ServletContextListener對ServletContext進行監聽。在web.xml中注冊該監聽器。
Spring 為該監聽器接口定義了一個實現類 ContextLoaderListener,完成了兩個很重要的工作:創建容器對象,并將容器對象放入到了 ServletContext 的空間中。
打開 ContextLoaderListener 的源碼。看到一共四個方法,兩個是構造方法,一個初始化方法,一個銷毀方法。
所以,在這四個方法中較重要的方法應該就是 contextInitialized(),context 初始化方法。
跟蹤 initWebApplicationContext()方法,可以看到,在其中創建了容器對象。
并且,將創建好的容器對象放入到了 ServletContext 的空間中,key 為一個常量:
WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE。
ContextLoaderListener 在對 Spring 容器進行創建時,需要加載 Spring 配置文件。其默認的 Spring 配置文件位置與名稱為:WEB-INF/applicationContext.xml。但,一般會將該配置文件放置于項目的 classpath 下,即 src 下,所以需要在 web.xml 中對 Spring 配置文件的位置及名稱進行指定。
從監聽器 ContextLoaderListener 的父類 ContextLoader 的源碼中可以看到其要讀取的配置文件位置參數名稱
contextConfigLocation。
在 Servlet 中獲取容器對象的常用方式有兩種:
● 直接從 ServletContext 中獲取
從對監聽器 ContextLoaderListener 的源碼分析可知,容器對象在 ServletContext 的中存放的 key 為
WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE。所以,可以直接通過 ServletContext 的 getAttribute()方法,按照指定的 key 將容器對象獲取到。
● 通過 WebApplicationContextUtils 獲取
工具類 WebApplicationContextUtils 有一個方法專門用于從 ServletContext 中獲取 Spring容器對象:
getRequiredWebApplicationContext(ServletContext sc)
查其源碼,看其調用關系,就可看到其是從 ServletContext 中讀取的屬性值,即 Spring容器。
以上兩種方式,無論使用哪種獲取容器對象,刷新 success 頁面后,可看到代碼中使用 的 Spring 容器均為同一個對象。