天天看點

springmvc源碼分析——入門看springmvc的加載過程

本文将分析springmvc是如何在容器啟動的時候将各個子產品加載完成容器的建立的。

我知道在web.xml檔案中我們是這樣配置springmvc的:

springmvc源碼分析——入門看springmvc的加載過程
可以看到,springmvc的核心控制器就是DispatcherServlet。看下DispatcherServlet的繼承關系:
springmvc源碼分析——入門看springmvc的加載過程

HttpSerlvetBean繼承自HttpServlet。

HttpServletBean覆寫了init方法,對初始化過程做了一些處理。這個方法是final的,也就是這個方法是不能被繼承的,是以我們就可以斷定spring在做這裡的時候,也就是初始化的時候的入口就是init方法,這個入口是不能被子類去實作的。init方法中執行了如下的操作:

springmvc源碼分析——入門看springmvc的加載過程
這裡我們重點關注一下用黑線标注的initServletBean(),try語句塊中的代碼是做一些跟springmvc配置檔案,以及資源檔案相關的初始化工作,我們不做深入的研究,隻需要知道相關的在web.xml檔案中的配置相關的資訊是在這裡處理的,我們重點關注一下springmvc整體的初始化流程,讓大家了解spring是如何加載的。好了我們看initServletBean()這個方法:
springmvc源碼分析——入門看springmvc的加載過程
這時候我們發現在httpServletBean的這個類中有這個方法,但是沒有實作,而且是一個protocted修飾的方法,這也就是說這個需要子類去實作,好了我們順着人家的代碼進入freamWorkServlet中:
springmvc源碼分析——入門看springmvc的加載過程
 此時的initServletBean()方法又是一個final修飾的方法,跟httpservletBean中的init()方法是一樣的,效果作用也一樣我們就不再贅述。這裡我們進入該方法的具體實作。我們發現這個時候在整個的方法中最關鍵的就是initWebApplicationContext()這個方法,我們大家對applicationContext應該是比較熟悉的,因為spring的容器其實就是一個context。這時候才是真正的開始容器的初始化。好了我們進入initWebApplicationContext()這個方法:
springmvc源碼分析——入門看springmvc的加載過程
在這個方法中代碼的前兩行,我們仍可以了解,因為springmvc的基于spring的,是以第一步是首先要去擷取parent父容器也就是spring的容器。然後開始根據父容器開始建立springmvc的容器。這裡我們再進入下一步之前,我覺着有必要對createWebApplicationContext(parent)這塊做一個簡答的解釋:
springmvc源碼分析——入門看springmvc的加載過程
其實整個這個處理的效果或者用途就是用來将目前的springmvc的容器與他的父容器進行一個關聯,比如:

wac.setParent(parent);
wac.setServletContext(getServletContext());
wac.setServletConfig(getServletConfig());
wac.setNamespace(getNamespace());      

最後将wac這個容器進行一個重新整理。

接下來我們傳回上一步,說到的對springmvc的容器和他的父容器進行一個關聯之後進行下一步的操作。 onRefresh(wac);

springmvc源碼分析——入門看springmvc的加載過程

在frameServlet中的initWebApplicationContext方法中的第三行代碼就是這句,但是我們在frameWorkServlet中看到

springmvc源碼分析——入門看springmvc的加載過程

同樣是一個沒有實作的方法,我們就應該可以推斷的出來這個方法的具體實作應該交給他的子類去處理,這時候我們就要進入到他的子類dispatcherServlet中看到的是如下的實作:

springmvc源碼分析——入門看springmvc的加載過程

    到這裡我相信大家應該比較看着順眼一些,這裡才是我們再日常的開發中接觸比較多的一些詞或者類。我們看到在dispaerServlet中的onRefresh()方法中隻有一個簡單的initStrategies()方法,看到這個詞Strategies,這是政策的意思,到這裡了跟大家說一下,springmvc中使用到的設計模式----政策模式。好了進入initStrategies()方法後,如上圖,這個時候springmvc就開始去加載對應的一些子產品中主要的元件,比如initMultipartResolver用來springmvc處理檔案的上傳,initLocaleResolver(context)用來處理國際話語言相關的一些操作,initThemeResolver()這個是用來處理一些有關動态更換樣式的支援(主題),initHandlerMappings()這個很重要處理我們經常聽到的有關url和controller的映射關系,initHandlerAdapters()處理映射有關的适配相關,initHandlerExceptionResolvers(context)用于springmvc有關異常的處理,initRequestToViewNameTranslator(context)處理請求到視圖名稱的一個轉換,initViewResolvers()處理視圖。針對這幾個政策今天就不細講。下次我們重點講各個政策在springmvc的初始化過程中是如何工作的。

    對springmvc的整個的加載過程做一個簡答的總結,在整個加載過程中httpServletBean是我們的入口,負責處理一些有關配置檔案或者資源的準備,這是因為我們很多的bean有可能依賴這些資源,然後調用initServletBean()方法開始servlet容器的建立工作,這時候httpServletBean隻是建立工作的入口,具體的建立是在他的子類frameWorkServlet中來做的,在frameWorkServlet中負責去跟父容器進行關聯,并建立createWebApplicationContext。然後進入onRefresh()方法也就是他的子類dispaerServlet中取按照政策模式的方式對springmvc中的具體的每個子產品進行初始化。是以整個過程我們發現springmvc在做初始化的時候每個類所做的工作是不一樣的,也是有分工的。httpservletBean主要是建立一些配置或資源檔案,frameWorkServlet主要是建立容器以及跟父容器的關聯。而在dispactorerServlet這個子類中才是真正的去做一些具體的初始化工作。

總結一下各個Servlet的作用:

1. HttpServletBean

 主要做一些初始化的工作,将web.xml中配置的參數設定到Servlet中。比如servlet标簽的子标簽init-param标簽中配置的參數。

2. FrameworkServlet

 将Servlet與Spring容器上下文關聯。其實也就是初始化FrameworkServlet的屬性webApplicationContext,這個屬性代表SpringMVC上下文,它有個父類上下文,既web.xml中配置的ContextLoaderListener監聽器初始化的容器上下文。

3. DispatcherServlet 

 初始化各個功能的實作類。比如異常處理、視圖處理、請求映射處理等。