本文將分析springmvc是如何在容器啟動的時候將各個模塊加載完成容器的創建的。
我知道在web.xml文件中我們是這樣配置springmvc的:

可以看到,springmvc的核心控制器就是DispatcherServlet。看下DispatcherServlet的繼承關系:

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

這里我們重點關注一下用黑線標注的initServletBean(),try語句塊中的代碼是做一些跟springmvc配置文件,以及資源文件相關的初始化工作,我們不做深入的研究,只需要知道相關的在web.xml文件中的配置相關的信息是在這里處理的,我們重點關注一下springmvc整體的初始化流程,讓大家了解spring是如何加載的。好了我們看initServletBean()這個方法:

這時候我們發現在httpServletBean的這個類中有這個方法,但是沒有實現,而且是一個protocted修飾的方法,這也就是說這個需要子類去實現,好了我們順着人家的代碼進入freamWorkServlet中:

此時的initServletBean()方法又是一個final修飾的方法,跟httpservletBean中的init()方法是一樣的,效果作用也一樣我們就不再贅述。這里我們進入該方法的具體實現。我們發現這個時候在整個的方法中最關鍵的就是initWebApplicationContext()這個方法,我們大家對applicationContext應該是比較熟悉的,因為spring的容器其實就是一個context。這時候才是真正的開始容器的初始化。好了我們進入initWebApplicationContext()這個方法:

在這個方法中代碼的前兩行,我們仍可以理解,因為springmvc的基於spring的,所以第一步是首先要去獲取parent父容器也就是spring的容器。然后開始根據父容器開始創建springmvc的容器。這里我們再進入下一步之前,我覺着有必要對createWebApplicationContext(parent)這塊做一個簡答的解釋:

其實整個這個處理的效果或者用途就是用來將當前的springmvc的容器與他的父容器進行一個關聯,比如:
wac.setParent(parent);
wac.setServletContext(getServletContext());
wac.setServletConfig(getServletConfig());
wac.setNamespace(getNamespace());
最后將wac這個容器進行一個刷新。
接下來我們返回上一步,說到的對springmvc的容器和他的父容器進行一個關聯之后進行下一步的操作。 onRefresh(wac);
在frameServlet中的initWebApplicationContext方法中的第三行代碼就是這句,但是我們在frameWorkServlet中看到
同樣是一個沒有實現的方法,我們就應該可以推斷的出來這個方法的具體實現應該交給他的子類去處理,這時候我們就要進入到他的子類dispatcherServlet中看到的是如下的實現:

到這里我相信大家應該比較看着順眼一些,這里才是我們再日常的開發中接觸比較多的一些詞或者類。我們看到在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
初始化各個功能的實現類。比如異常處理、視圖處理、請求映射處理等。
