一、时序图

spring MVC时序图,描述代理对象生成及拦截器执行流程。由于图片过大,此处不做截图展示。
git地址有详细时序图,有相应的html文件可以直接浏览
地址: https://github.com/13162576590/spring-source-study

二、Spring MVC源码

Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。使用 Spring 可插入的 MVC 架构,从而在使用Spring进行WEB开发时,可以选择使用Spring的Spring MVC框架或集成其他MVC开发框架。

RequestMappingHandlerMapping 映射器,只要类上有 ControllerRequestMapping 注解,就符合该映射器管辖范围。默认会自动加载所有实现HandlerMapping接口的bean,且我们可以通过serOrder来设置优先级,系统默认会加载RequestMappingHandlerMapping、BeanNameUrlHandlerMapping、SimpleUrlHandlerMapping 并且按照顺序使用。

HandlerMappingsDispathServlet中主要作用是为请求的urlpath匹配对应的Controller,建立一个映射关系,根据请求查找HandlerInterceptorHandlerMappings将请求传递到HandlerExecutionChain上,HandlerExecutionChain包含了一个能够处理该请求的处理器,还可以包含拦截改请求的拦截器。

url和Controller映射关系初始化。在IOC容器初始化中,已经了解到一个Bean如何初始化,url与Controller的映射关系也在这个过程中完成的。入口在AbstractAutowireCapableBeanFactory类protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd)方法。

当初始化RequestMappingHandlerMapping时,RequestMappingHandlerMapping映射器就会处理url与Controller的映射关系。
进入AbstractAutowireCapableBeanFactory类protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd)方法
  invokeInitMethods(beanName, wrappedBean, mbd);
	继续调用AbstractAutowireCapableBeanFactory类方法
  1、protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
			throws Throwable方法
    invokeInitMethods(beanName, wrappedBean, mbd);

初始化RequestMappingHandlerMapping相应Bean时,进入RequestMappingHandlerMapping类的public void afterPropertiesSet()方法
  ((InitializingBean) bean).afterPropertiesSet();

进入AbstractHandlerMethodMapping类public void afterPropertiesSet()方法
  super.afterPropertiesSet();
	继续调用AbstractAutowireCapableBeanFactory类方法
  1、protected void initHandlerMethods()方法
    initHandlerMethods();
	2、protected void processCandidateBean(String beanName)方法
    processCandidateBean(beanName);
	3、protected void detectHandlerMethods(Object handler)方法
    detectHandlerMethods(beanName);
  
进入MethodIntrospector类public static <T> Map<Method, T> selectMethods(Class<?> targetType, final MetadataLookup<T> metadataLookup)方法
			Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
					(MethodIntrospector.MetadataLookup<T>) method -> {
						try {
							return getMappingForMethod(method, userType);
						}
						catch (Throwable ex) {
							throw new IllegalStateException("Invalid mapping on handler class [" +
									userType.getName() + "]: " + method, ex);
						}
					});

进入ReflectionUtils类public static void doWithMethods(Class<?> clazz, MethodCallback mc, @Nullable MethodFilter mf)方法
  ReflectionUtils.doWithMethods(currentHandlerType, method -> {
				Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass);
				T result = metadataLookup.inspect(specificMethod);
				if (result != null) {
					Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
					if (bridgedMethod == specificMethod || metadataLookup.inspect(bridgedMethod) == null) {
						methodMap.put(specificMethod, result);
					}
				}
			}, ReflectionUtils.USER_DECLARED_METHODS);

回到MethodIntrospector类public static <T> Map<Method, T> selectMethods(Class<?> targetType, final MetadataLookup<T> metadataLookup)方法,会进入回调方法。
  //此出回调传入的方法,见下方源码处
  mc.doWith(method);
  源码如下:
	//传入一个MethodCallback的回调,当回调时进入方法内部执行
	ReflectionUtils.doWithMethods(currentHandlerType, method -> {
				Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass);
				T result = metadataLookup.inspect(specificMethod);
				if (result != null) {
					Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
					if (bridgedMethod == specificMethod || metadataLookup.inspect(bridgedMethod) == null) {
						methodMap.put(specificMethod, result);
					}
				}
			}, ReflectionUtils.USER_DECLARED_METHODS);

进入ClassUtils类public static Method getMostSpecificMethod(Method method, @Nullable Class<?> targetClass)方法
  //获取目标类方法,回调方法中调用
  Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass);

回到AbstractHandlerMethodMapping类protected void detectHandlerMethods(Object handler)方法
  //此出回调传入的方法,见下方源码处
  T result = metadataLookup.inspect(specificMethod);
	源码如下:
    	//传入一个MetadataLookup的回调,当回调时进入方法内部执行
			Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
					(MethodIntrospector.MetadataLookup<T>) method -> {
						try {
							return getMappingForMethod(method, userType);
						}
						catch (Throwable ex) {
							throw new IllegalStateException("Invalid mapping on handler class [" +
									userType.getName() + "]: " + method, ex);
						}
					});
	
再次回到类,调用protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType)方法
  //回调方法中调用
  return getMappingForMethod(method, userType);
	继续调用RequestMappingHandlerMapping类方法
  1、private RequestMappingInfo createRequestMappingInfo(AnnotatedElement element)方法
    //构建一个RequestMappingInfo,根据method构建,当method构建不为空时,在根据目标类构建前缀路径
    RequestMappingInfo info = createRequestMappingInfo(method);
		源码:
    protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
      //method构建
      RequestMappingInfo info = createRequestMappingInfo(method);
      if (info != null) {
        //目标类构建,及handle
        RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType);
        if (typeInfo != null) {
          //路径信息合并
          info = typeInfo.combine(info);
        }
        String prefix = getPathPrefix(handlerType);
        if (prefix != null) {
          info = RequestMappingInfo.paths(prefix).options(this.config).build().combine(info);
        }
      }
      return info;
    }

再次回到MethodIntrospector类public static <T> Map<Method, T> selectMethods(Class<?> targetType, final MetadataLookup<T> metadataLookup)方法,再其回调方法内部,进入BridgeMethodResolver类public static Method findBridgedMethod(Method bridgeMethod)方法,最后在methodMap中缓存方法。
  Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
	//缓存map
	final Map<Method, T> methodMap = new LinkedHashMap<>();


再次回到AbstractHandlerMethodMapping类protected void detectHandlerMethods(Object handler)方法。
  回到以下代码处:
  methods.forEach((method, mapping) -> {
    Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
    //进入RequestMappingHandlerMapping类protected void registerHandlerMethod(Object handler, Method method, RequestMappingInfo mapping)方法
    registerHandlerMethod(handler, invocableMethod, mapping);
  });
  
进入RequestMappingHandlerMapping类protected void registerHandlerMethod(Object handler, Method method, RequestMappingInfo mapping)方法
  registerHandlerMethod(handler, invocableMethod, mapping);

再次进入AbstractHandlerMethodMapping类,调用protected void registerHandlerMethod(Object handler, Method method, T mapping)方法
  super.registerHandlerMethod(handler, method, mapping);
	继续调用AbstractHandlerMethodMapping类方法
	1、public void register(T mapping, Object handler, Method method)方法
    mappingRegistry.register(mapping, handler, method);
	2、protected HandlerMethod createHandlerMethod(Object handler, Method method)方法
    //构建一个HandlerMethod
    HandlerMethod handlerMethod = createHandlerMethod(handler, method);
		//缓存handlerMethod与handlerMethod的映射关系到mappingLookup中
		mappingLookup.put(mapping, handlerMethod);
		private final Map<T, HandlerMethod> mappingLookup = new LinkedHashMap<>();
	3、private List<String> getDirectUrls(T mapping)方法
    List<String> directUrls = getDirectUrls(mapping);
		//缓存url与mapping的映射关系到urlLookup中
		urlLookup.add(url, mapping);
		private final MultiValueMap<String, T> urlLookup = new LinkedMultiValueMap<>();
	注册mapping与MappingRegistration映射关系到registry中
		this.registry.put(mapping, new MappingRegistration<>(mapping, handlerMethod, directUrls, name));
		private final Map<T, MappingRegistration<T>> registry = new HashMap<>();
	至此完成url及handle的映射关系。

spring MVC初始化入口,这个应该比较熟悉,在spring boot未流行时,需要配置很多的配置文件,其中最为熟悉就是web.xml吧,其初始化入口就是DispatcherServlet类。其配置如下:

<servlet>  
  <!-- 配置DispatcherServlet -->  
  <servlet-name>springMvc</servlet-name>  
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
  <!-- 指定spring mvc配置文件位置 不指定使用默认情况 -->  
  <init-param>     
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:spring/spring-mvc.xml</param-value>
  </init-param>  
  <!-- 设置启动顺序 -->  
  <load-on-startup>1</load-on-startup>  
</servlet>

<!-- ServLet 匹配映射 -->
<servlet-mapping>
  <servlet-name>springMvc</servlet-name>
  <url-pattern>/</url-pattern>
</servlet-mapping>

首先找到DispatcherServlet这个类,必然是寻找init()方法。然后,我们发现其init方法其实在父类HttpServletBean中。

进入DispatcherServlet类,发现并未有init()方法,因此进入其父类FrameworkServlet继续寻找,但是在FrameworkServlet类仍未找到,故继续进入其父类HttpServletBean类,终于找到其初始化方法public final void init() throws ServletException,该方法就是其初始化的入口,下面基于该方法分析。

进入HttpServletBean类public final void init() throws ServletException方法
  //初始化servlet
  initServletBean();
  该方法中核心方法 initServletBean()。

进入FrameworkServlet类protected final void initServletBean() throws ServletException方法
  initServletBean();
	继续调用FrameworkServlet类方法
  1、protected WebApplicationContext initWebApplicationContext()方法
  	this.webApplicationContext = initWebApplicationContext();

进入DispatcherServlet类protected void onRefresh(ApplicationContext context)方法
  onRefresh(wac);
	继续调用DispatcherServlet类方法
  1、protected void initStrategies(ApplicationContext context)方法
    initStrategies(context);
		该方法主要是初始化九大组件,源码如下:
    //初始化策略
    protected void initStrategies(ApplicationContext context) {
    	//多文件上传的组件 
      initMultipartResolver(context); 
      //初始化本地语言环境 
      initLocaleResolver(context); 
      //初始化模板处理器 
      initThemeResolver(context); 
      //handlerMapping 
      initHandlerMappings(context); 
      //初始化参数适配器 
      initHandlerAdapters(context); 
      //初始化异常拦截器 
      initHandlerExceptionResolvers(context); 
      //初始化视图预处理器 
      initRequestToViewNameTranslator(context); 
      //初始化视图转换器 
      initViewResolvers(context);
      //FlashMap 管理器
      initFlashMapManager(context); 
    }
	2、private void initHandlerMappings(ApplicationContext context)方法
    initHandlerMappings(context);
	
进入BeanFactoryUtils类public static <T> Map<String, T> beansOfTypeIncludingAncestors(
			ListableBeanFactory lbf, Class<T> type, boolean includeNonSingletons, boolean allowEagerInit)
			throws BeansException 方法
  Map<String, HandlerMapping> matchingBeans =
  BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);

进入AbstractApplicationContext类public <T> Map<String, T> getBeansOfType(@Nullable Class<T> type, boolean includeNonSingletons, boolean allowEagerInit) throws BeansException方法
  result.putAll(lbf.getBeansOfType(type, includeNonSingletons, allowEagerInit));

进入DefaultListableBeanFactory类public <T> Map<String, T> getBeansOfType(@Nullable Class<T> type, boolean includeNonSingletons, boolean allowEagerInit) throws BeansException方法
  return getBeanFactory().getBeansOfType(type, includeNonSingletons, allowEagerInit);
	继续调用DefaultListableBeanFactory类方法
  1、public String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit)方法
    String[] beanNames = getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
	2、private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit)方法
    return doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit);

运行阶段,这一步是由请求触发的,所以入口为 DispatcherServlet 的核心方法为 doService(), doService()中的核心逻辑由 doDispatch()实现,流程分析如下:

进入DispatcherServlet类protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception方法
  继续调用DispatcherServlet类方法
  1、protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception方法
  	 doDispatch(request, response);
	2、protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException方法
		// 检查是否是文件上传的请求 
    processedRequest = checkMultipart(request);
	3、protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception方法
    // 取得处理当前请求的 Controller,这里也称为 hanlder,处理器,
    // 第一个步骤的意义就在这里体现了.这里并不是直接返回 Controller,
    // 而是返回的 HandlerExecutionChain 请求处理器链对象,
    // 该对象封装了 handler 和 interceptors.
		mappedHandler = getHandler(processedRequest);
		源码如下:
    @Nullable
    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
      if (this.handlerMappings != null) {
        //遍历所有handler,当遍历到RequestMappingHandlerMapping时,进入AbstractHandlerMapping类public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception方法
        for (HandlerMapping mapping : this.handlerMappings) {
          HandlerExecutionChain handler = mapping.getHandler(request);
          if (handler != null) {
            return handler;
          }
        }
      }
      return null;
    }
进入AbstractHandlerMapping类public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception方法
  HandlerExecutionChain handler = mapping.getHandler(request);

进入RequestMappingInfoHandlerMapping类protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception方法
  Object handler = getHandlerInternal(request);
进入AbstractHandlerMethodMapping类protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception方法
  return super.getHandlerInternal(request);
进入UrlPathHelper类public String getLookupPathForRequest(HttpServletRequest request)方法
  String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);

回到AbstractHandlerMethodMapping类protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception方法
  继续调用AbstractHandlerMethodMapping方法
	1、protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception方法
  HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
	//得到RequestMappingInfo列表,最终得到一个最优RequestMappingInfo
	List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
回到AbstractHandlerMethodMapping类public HandlerMethod createWithResolvedBean()方法,继续执行,进入HandlerMethod类public HandlerMethod createWithResolvedBean()方法
  //方法内部通过IOC容器获取handler及Controller,此处是一个cglib的代理对象,最终得到一个HandlerMethod对象
  return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
回到AbstractHandlerMapping类public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception方法
  继续调用AbstractHandlerMapping类方法
  1、protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) 方法
  	//继续此处执行,得到一个执行链
  	HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
再次回到DispatcherServlet类protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception方法
  继续调用DispatcherServlet类方法
  1、protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException方法  
    //获取处理request的处理器适配器handler adapter
    HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
进入AbstractHandlerMethodAdapter类public final ModelAndView handle(HttpServletRequest request, 		HttpServletResponse response, Object handler) throws Exception方法
  mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
进入RequestMappingHandlerAdapter类protected ModelAndView handleInternal(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception方法
  return handleInternal(request, response, (HandlerMethod) handler);
	继续调用RequestMappingHandlerAdapter类方法
  1、protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception方法
    mav = invokeHandlerMethod(request, response, handlerMethod);
进入ServletInvocableHandlerMethod类public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception方法
  invocableMethod.invokeAndHandle(webRequest, mavContainer);
进入InvocableHandlerMethod类public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception方法
  Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
	继续调用InvocableHandlerMethod类方法
  1、protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception方法
    //获取方法参数值,绑定参数
		Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
进入HandlerMethodArgumentResolverComposite类public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
			NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception方法
	args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
回到InvocableHandlerMethod类public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception方法,继续执行
  继续调用InvocableHandlerMethod类方法
  1、protected Object doInvoke(Object... args) throws Exception方法
  	return doInvoke(args);
		//通过桥接方法反射调用,最终进入目标类目标方法,其执行和AOP拦截链流程一致,此处不再分析
		return getBridgedMethod().invoke(getBean(), args);
再次回到ServletInvocableHandlerMethod类public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception方法,继续往下执行
  	//此处得到执行返回值
  	Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
进入HandlerMethodReturnValueHandlerComposite类public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception方法
进入HandlerMethodReturnValueHandlerComposite类public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception方法
		//处理返回值
		returnValueHandlers.handleReturnValue(returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
	继续调用HandlerMethodReturnValueHandlerComposite类方法
  1、private HandlerMethodReturnValueHandler selectHandler(@Nullable Object value, MethodParameter returnType)方法
    //次处HandlerMethodReturnValueHandler是一个RequestResponseBodyMethodProcessor
  	HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType);
进入RequestResponseBodyMethodProcessor类public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
			throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException方法
		handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
	源码:
	@Override
	public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
			ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
			throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {

		mavContainer.setRequestHandled(true);
    //创建一个ServletServerHttpRequest
		ServletServerHttpRequest inputMessage = createInputMessage(webRequest);
    //创建一个ServletServerHttpResponse
		ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);

		// Try even with null return value. ResponseBodyAdvice could get involved.
		writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
	}
	继续调用RequestResponseBodyMethodProcessor类方法
  1、protected <T> void writeWithMessageConverters(@Nullable T value, MethodParameter returnType,
			ServletServerHttpRequest inputMessage, ServletServerHttpResponse outputMessage)
			throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException方法
    	//遍历消息数据转换器进行匹配,获取body
    	body = getAdvice().beforeBodyWrite(body, returnType, selectedMediaType,
							(Class<? extends HttpMessageConverter<?>>) converter.getClass(),
							inputMessage, outputMessage);

进入AbstractHttpMessageConverter类public final void write(final T t, @Nullable MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException方法
  //将数据转换为配置的数据格式
  ((HttpMessageConverter) converter).write(body, selectedMediaType, outputMessage);
回到RequestMappingHandlerAdapter类protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception方法,继续往下执行
  //获取ModelAndView
  return getModelAndView(mavContainer, modelFactory, webRequest);
最终回到DispatcherServlet类protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception方法继续执行
  //结果视图对象的处理
  applyDefaultViewName(processedRequest, mv);