天天看點

深入了解SpringMVC源碼解析

Spring MVC的使用原理其實是通過配置一個Servlet來接管所有的請求,所有的請求由這個Servlet來進行分發處理。

我們可以從web.xml裡面看出這一點

這個Servlet就是Spring MVC提供的DispatcherServlet,它的繼承圖如下:

DispatcherServlet大緻接收請求的時序圖如下:

下面我們先設定幾個問題然後再去看源碼。

DispatcherServlet初始化的時機?

我們将斷點打在DispatcherServlet中的onRefresh方法上

,然後啟動項目。

從這個堆棧的圖可以看出,最開始是HttpServletBean的init方法執行,然後啟動Spring容器,Spring容器初始化的最後一步finishRefresh裡面進行了事件通知。

FrameworkServlet裡有個内部類ContextRefreshListener,實作了ApplicationListener接口,接收到了上面的事件通知,執行onApplicationEvent方法。

繼續跟蹤onApplicationEvent方法

發現最終是由onRefresh方法來進行具體處理的,并且這個onRefresh方法在FrameworkServlet裡面是個空方法,是由它的子類DispatcherServlet來實作的。

我們來看DispatcherServlet裡的onRefresh方法

這樣就把SpringMVC的九大元件給初始化了。

我們的@RequestMapping注解在方法上,SpringMVC是怎麼根據這個注解就能将對應的請求執行到這個方法上的?

從上面可以看到有個initHandlerMappings方法:

繼續跟蹤getDefaultStrategies方法

可以看出對classNames進行了周遊,這裡有兩個值,

BeanNameUrlHandlerMapping和RequestMappingHandlerMapping,我們一般用的是RequestMappingHandlerMapping。

RequestMappingHandlerMapping的父類AbstractHandlerMethodMapping實作了InitializingBean接口,我們來看看它實作的afterPropertiesSet方法。

前面都是一些配置,後面是調用父類的afterPropertiesSet方法,此方法裡隻有initHandlerMethods一個方法

主要看processCandidateBean方法

繼續跟蹤detectHandlerMethods方法

繼續跟蹤裡面的register方法

可以看出mappingLookup、urlLookup、registry都放入了值。這時我也不知道每個的具體作用。我把斷點打到這3個屬性上。然後前端發起一個get請求。

請求比對的過程?

前端發起請求,斷點停在了AbstractHandlerMethodMapping.MappingRegistry#getMappingsByUrl方法上,以前端發起的請求路徑,從urlLookup上擷取對應的值。

最後看看請求分發的主流程,也是springMVC最核心的代碼

總結:

tomcat的Servlet調起Spring容器啟動,Spring容器啟動完,事件通知到SpringMVC的DispatcherServlet。

這時會掃描所有的bean,将注解了@Controller和@RequestMapping的解析出來。

前端請求發過來,DispatcherServlet接收到(因為它是個servlet,配置在web.xml的),根據上一步處理好的映射關系,找到對應的方法來處理。

如通過/test能找到test方法

找到對應的方法後,反射調用

組裝modelAndView渲染視圖到前端

書山有路勤為徑,學海無涯苦作舟