SpringMvc原始碼解讀筆記
工作機制中分三部來分析springmvc的原始碼
- ApplicationContext初始化時建立所有url和controller類的對應關係(用Map儲存)
- 根據請求url找到對應的controller,並從controller中找到處理請求的方法
- request引數繫結到方法的形參,執行方法處理請求,並返回結果檢視
ApplicationContext初始化時建立所有url和controller類的對應關係(用Map儲存)
Sptingboot中的呼叫鏈
RequestMappingHandlerMapping的注入依靠的是springboot的自動裝配
1、自動裝配:在spring-boot-autoconfigure包的spring.factories裡面的WebMvcAutoConfiguration
2、WebMvcAutoConfiguration的內部類EnableWebMvcConfiguration#requestMappingHandlerMapping()
3、WebMvcConfigurationSupport#requestMappingHandlerMapping()
Spring中的呼叫鏈
1、springmvc開啟註解宣告,需要在xml中加入<mvc:annotation-driven/>標籤
2、spring容器啟動,掃描xml,載入BeanDefinition過程中,掃描到annotation-driven標籤,使用AnnotationDrivenBeanDefinitionParser解析
3、AnnotationDrivenBeanDefinitionParser的parse方法將RequestMappingHandlerMapping註冊到beanDefinition集合中
主要註冊HandlerMappings-路徑匹配器
、HandlerAdapters-路徑匹配介面卡
HandlerExceptionResolvers-異常解析器
、AntPathMatcher-路徑解析器
、UrlPathHelper-請求路徑獲取幫助類
等beans,提前為mvc做好基礎的準備
4、beanFactory根據BeanDefinition生成bean
1、web.xml中配置DispatcherServlet
2、DispatcherServlet#onRefresh()
3、DispatcherServlet#initStrategies()
4、DispatcherServlet#initHandlerMappings()
AbstractApplicationContext#refresh() --> AbstractApplicationContext#finishBeanFactoryInitialization() --> DefaultListableBeanFactory#preInstantiateSingletons() --> AbstractBeanFactory#getBean() --> AbstractBeanFactory#doGetBean() --> AbstractAutowireCapableBeanFactory#createBean() --> AbstractAutowireCapableBeanFactory#doCreateBean() --> AbstractAutowireCapableBeanFactory#initializeBean() --> // 前面都是spring的啟動過程 AbstractAutowireCapableBeanFactory#invokeInitMethods() --> RequestMappingHandlerMapping#afterPropertiesSet() --> // 上面三行都是bean的生命週期過程 // 下面開始是重點 AbstractHandlerMethodMapping#afterPropertiesSet() --> // 獲取所有不以scopedTarget.開頭的beanName AbstractHandlerMethodMapping#initHandlerMethods() --> // 獲取所有帶有Controller或者RequestMapping註解的bean的Class物件 AbstractHandlerMethodMapping#processCandidateBean --> // 找出該Controller下的所有帶RequestMapping註解的函式 AbstractHandlerMethodMapping#detectHandlerMethods() --> // 開始註冊對映 RequestMappingHandlerMapping#registerHandlerMethod() --> // 將對映關係放入AbstractHandlerMethodMapping.mappingRegistry.registry中 AbstractHandlerMethodMapping#registerHandlerMethod()
根據請求url找到對應的controller,並從controller中找到處理請求的方法
DispatcherServlet的初始化
自動裝配:在spring-boot-autoconfigure包的spring.factories裡面的DispatcherServletAutoConfiguration
@Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
public DispatcherServlet dispatcherServlet(WebMvcProperties webMvcProperties) {
xxx
return dispatcherServlet;
}
getHandler(processedRequest)方法實際上就是從HandlerMapping中找到url和controller的對應關係.這也就是第一個步驟:建立Map<url,Controller>的意義
DispatcherServlet#doDispatch()
// 獲取處理器(處理器就是controller)
DispatcherServlet#getHandler()
AbstractHandlerMapping#getHandler()
// 獲取請求路徑,根據請求路徑查詢處理器
RequestMappingInfoHandlerMapping#getHandlerInternal()
AbstractHandlerMethodMapping#getHandlerInternal()
// 查詢處理器的方法
AbstractHandlerMethodMapping#lookupHandlerMethod()
request引數繫結到方法的形參,執行方法處理請求,並返回結果檢視
controller的呼叫過程
DispatcherServlet#doDispatch()
AbstractHandlerMethodAdapter#handle()
RequestMappingHandlerAdapter#handleInternal()
// 在這裡會建立ServletInvocableHandlerMethod,此時已經將controller的函式(HandlerMethod)的引數注入到InvocableHandlerMethod(類變數)中
RequestMappingHandlerAdapter#invokeHandlerMethod()
ServletInvocableHandlerMethod#invokeAndHandle()
// 在此方法中通過反射的方式呼叫controller中的方法
ServletInvocableHandlerMethod#invokeForRequest()
// 以下是引數處理過程
InvocableHandlerMethod#getMethodArgumentValues()
// 這裡會呼叫getArgumentResolver,根據引數的型別決定使用哪種HandlerMethodArgumentResolver
// 引數處理器是否支援該引數是由supportsParameter方法決定
HandlerMethodArgumentResolverComposite#resolveArgument()
// 例如:引數有RequestBody註解就會使用RequestResponseBodyMethodProcessor引數處理器
RequestResponseBodyMethodProcessor#resolveArgument()
// 呼叫json工具將引數轉換成相應的Object
RequestResponseBodyMethodProcessor#readWithMessageConverters()
返回值的處理過程
ServletInvocableHandlerMethod#invokeAndHandle()
// 選擇相應的HandlerMethodReturnValueHandler並執行
HandlerMethodReturnValueHandlerComposite#handleReturnValue()
ModelAndView由返回值處理器ModelAndViewMethodReturnValueHandler處理
參考文章:
springmvc工作原理以及原始碼分析(基於spring3.1.0) - heavenyes - 部落格園 (cnblogs.com)
SpringMVC原始碼之Handler註冊、獲取以及請求controller中方法 - 嗶哩嗶哩 (bilibili.com)
SpringMvc RequestMappingHandlerMapping - 喜歡日向雛田一樣的女子啊 - 部落格園 (cnblogs.com)