SpringMVC之RequestMapping執行過程(HandlerAdapter篇)
寫在前面
如果想搞清楚 引數解析 和 結果集處理 的邏輯,RequestMappingHandlerAdapter 是我們必須要弄明白的類。
下面以一段 Hello World 程式碼為例:
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; @Controller public class HelloController { @RequestMapping(value="/sayHello") @ResponseBody public String printHello(@RequestParam(defaultValue = "guest") String name) { return "hello, " + name; } }
說得通俗一點,就是 printHello 執行之前,SpringMVC 框架幹了點什麼? printHello 返回值之後,SpringMVC 框架幹了點什麼? printHello 假如發生了異常,SpringMVC 框架又為我們看了點什麼?
概述 RequestMappingHandlerAdapter
RequestMappingHandlerAdapter 有兩個成員變數:
-
HandlerMethodArgumentResolverComposite 本身也是實現 HandlerMethodArgumentResolver 介面的,還包含一組 HandlerMethodArgumentResolver
-
HandlerMethodReturnValueHandlerComposite 實現了 HandlerMethodReturnValueHandler 介面,同時還包含一組 HandlerMethodReturnValueHandler 介面例項,目的也是包裝迴圈的程式碼。
初始化 RequestMappingHandlerAdapter
RequestMappingHandlerAdapter 又實現了 InitializingBean 介面,因此在 Spring 容器載入該 Bean 時,會觸發 afterPropertiesSet()
Spring中的InitializingBean介面的使用 介紹了 Spring Bean 初始化的兩個方法,一個是實現 InitializingBean,另一個是 init-method 。
那麼複習一下,RequestMappingHandlerAdapter 加入到 Spring 容器中的時機是什麼時候呢?
答:在 DispatcherServlet # initStrategies 中呼叫 initHandlerAdapters 初始化 處理器介面卡。
想進一步瞭解該知識點的,可以參考這篇文章 詳細解讀 DispatcherServlet 初始化過程(帶時序圖)
初始化 RequestMappingHandlerAdapter Bean 的過程如圖所示:
@Override
public void afterPropertiesSet() {
// Do this first, it may add ResponseBody advice beans
initControllerAdviceCache();
// 獲取引數解析器
if (this.argumentResolvers == null) {
List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
}
// @InitBinder 註解相關的引數解析器
if (this.initBinderArgumentResolvers == null) {
List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();
this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
}
// 獲取返回值處理器
if (this.returnValueHandlers == null) {
List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
}
}
總結
RequestMappingHandlerAdapter 是 SpringMVC 實現 引數解析 和 結果集處理 的核心類之一。
其中,解析引數的介面為 HandlerMethodArgumentResolver
處理結果集的介面為 HandlerMethodReturnValueHandler
RequestMappingHandlerAdapter 實現了 InitializingBean,因此初始化的過程在 afterPropertiesSet() 方法中。
在 getDefaultArgumentResolvers() 方法中,我們可以找到各種各樣常見的引數是如何解析的。
在 getDefaultReturnValueHandlers() 方法中,我們可以找到各種各樣常見的返回值是如何處理的。