1. 程式人生 > 其它 >SpringMvc原始碼解讀筆記

SpringMvc原始碼解讀筆記

工作機制中分三部來分析springmvc的原始碼

  1. ApplicationContext初始化時建立所有url和controller類的對應關係(用Map儲存)
  2. 根據請求url找到對應的controller,並從controller中找到處理請求的方法
  3. 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)