天天看點

SpringMVC之淺析上下文初始化(一)

說明:本文所用的SpringMVC版本為4.3.4.RELEASE,應用伺服器為TomCat8.0.33。下面我們先回顧一下我們在用SpringMVC進行開發時在web.xml中進行的一些配置:

上面的代碼,基本上是我們用哪個SpringMVC開發時進行的一些配置。那麼這些配置都用什麼用呢?下面我們來一點一點進行分析:

ContextLoaderListener上下文監聽器。ContextLoaderListener的作用是Web容器啟動的時候,自動裝配ApplicationContext的配置資訊,即初始化Spring IOC容器。我們看一下這個類的繼承關系:

SpringMVC之淺析上下文初始化(一)

。從圖中我們可以看出ContextLoaderListener實作了ServletContextListener(Servlet上下文監聽器)接口。我們簡單說一下ServletContextListener的作用:ServletContextListener中有兩個方法,一個是contextInitialized一個是contextDestroyed。每一個應用都有ServletContext與之相關聯,ServletContext中存放了一些web應用全局性的配置。當Servlet容器啟動的時候,會執行個體化和ServletContext相關的一些類。如ApplicationContext(注意不是Spring中的那個ApplicationContext)、ApplicationContexFacade、ServletConfig、ServletContextEvent以及ServletContextListener的實作類等等,并調用contextInitialized方法進行一些上下文初始化相關的動作。當Servlet容器關閉的時候,會調用contextDestroyed銷毀上下文相關的内容。即ServletContextListener是和ServletContext的生命周期相關聯的。ContextLoaderListener實作了ServletContextListener接口,是以當容器啟動的時候,會調用ContextLoaderListener中的contextInitialized方法,進行一系列的初始化的動作。

而<context-param>中的内容即是ServletContext中的一些配置資訊。

下面我們看一下從容器啟動到調用到contextInitialized方法的調用鍊:

SpringMVC之淺析上下文初始化(一)

從上圖中我們可以看到在org.apache.catalina.core.StandardContext#listenerStart的方法中調用了contextInitialized的方法,進行上下文的初始化。PS:StandardContex是TomCat體系中很重要的一個類,可以找時間說一下TomCat的大緻體系結構,網上也有很多資料。下面我們看一下在ContextLoaderListener中的contextInitialized中發生了什麼。

ContextLoaderListener中的内容很簡單,就是調用了initWebApplicationContext這個方法,并把ServletContext的實作類(ApplicationContextFacade)傳進去。initWebApplicationContext這個方法在ContextLoader這個類中,ContextLoaderListener繼承了ContextLoader這個類,其實主要的調用邏輯都在ContextLoader這個類中。我們就進入到initWebApplicationContext這個方法中,看看代碼中是怎麼寫的(去掉了無關的代碼):

假設我們的this.context為null(這裡我們隻考慮正常的一般場景),我們繼續到createWebApplicationContext方法中,看一下是怎麼建立Spring web上下文的:

上面的代碼很簡單:查找WebApplicationContext的實作類,然後通過反射的方式執行個體化。執行個體化的過程不用多說,我們看一下determineContextClass這個方法。

從上面的代碼中我們可以看出,我們可以配置在web.xml中配置WebApplicationContext的實作類,如果沒有在web.xml中進行配置的話,則取預設的實作類。下面我們看一下是怎麼去預設的實作類的:

在ContextLoader中有這樣的一段代碼:

靜态代碼塊,我們知道在類初始化的時候會執行靜态代碼塊。是以在ContextLoader執行個體化之前已經加載過了ContextLoader.properties配置檔案。我們看一下ContextLoader.properties中的内容:

我們發現這裡就一個配置項,預設配置了一個WebApplicationContext的實作類:XmlWebApplicationContext。是以如果我們沒有在web.xml中進行配置的話,這裡就會執行個體化XmlWebApplicationContext這個類。

下面我們回到initWebApplicationContext這個方法中繼續分析。因為我們的Context是剛執行個體化的,而active的預設值是false,是以會進入到if中,同樣cwac.getParent()==null成立,是以會執行loadParentContext()這個方法。我們看看這個方法中做了什麼操作:

loadParentContext主要做的就是從web.xml中加載父應用上下文。

下面就到了我們最重要的一個方法了configureAndRefreshWebApplicationContext了。接下來我們的分析也就是圍繞這個類了:

在上面的代碼中我們分析一下customizeContext這個方法,對于wac.refresh();這個方法我們這裡就先不展開了。因為這個方法是SpringIOC容器初始化的入口。内容太多了,我們以後在分析Spring的源碼時再詳細的說明。

下面我們看一下determineContextInitializerClasses這個查找初始化類的方法

OK,到這裡我們關于Spring Web上下文的分析就先到這裡了。這裡初始化了一個父的IOC容器。下篇文章我們接着分析DispatcherServlet的初始化過程。

其時序圖如下:

SpringMVC之淺析上下文初始化(一)

資料:

線程上下文:

http://blog.csdn.net/zhoudaxia/article/details/35897057