08、SpringMVC源码分析 - RequestMappingHandlerAdapter

一、实例化

WebMvcConfigurationSupport.java

@Bean
	public RequestMappingHandlerAdapter requestMappingHandlerAdapter(
			@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
			@Qualifier("mvcConversionService") FormattingConversionService conversionService,
			@Qualifier("mvcValidator") Validator validator) {
   
     

		RequestMappingHandlerAdapter adapter = createRequestMappingHandlerAdapter();
		adapter.setContentNegotiationManager(contentNegotiationManager);
		//WebMvcConfigurer接口实现类的configureMessageConverters,消息转换器
		adapter.setMessageConverters(getMessageConverters());
		adapter.setWebBindingInitializer(getConfigurableWebBindingInitializer(conversionService, validator));
		//WebMvcConfigurer接口实现类的addArgumentResolvers,定制参数解析器
		adapter.setCustomArgumentResolvers(getArgumentResolvers());
		//WebMvcConfigurer接口实现类的addReturnValueHandlers,定制返回值解析器
		adapter.setCustomReturnValueHandlers(getReturnValueHandlers());

		if (jackson2Present) {
   
     
			adapter.setRequestBodyAdvice(Collections.singletonList(new JsonViewRequestBodyAdvice()));
			adapter.setResponseBodyAdvice(Collections.singletonList(new JsonViewResponseBodyAdvice()));
		}

		AsyncSupportConfigurer configurer = getAsyncSupportConfigurer();
		if (configurer.getTaskExecutor() != null) {
   
     
			adapter.setTaskExecutor(configurer.getTaskExecutor());
		}
		if (configurer.getTimeout() != null) {
   
     
			adapter.setAsyncRequestTimeout(configurer.getTimeout());
		}
		adapter.setCallableInterceptors(configurer.getCallableInterceptors());
		adapter.setDeferredResultInterceptors(configurer.getDeferredResultInterceptors());

		return adapter;
	}

二、初始化

1、afterPropertiesSet( )

@Override
	public void afterPropertiesSet() {
   
     
		// Do this first, it may add ResponseBody advice beans
		//初始化@ControllerAdvice、@RestControllerAdvice标识的类
		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);
		}
	}

2、initControllerAdviceCache( )

private void initControllerAdviceCache() {
   
     
		if (getApplicationContext() == null) {
   
     
			return;
		}
		
		//获取@ControllerAdvice的Bean
		List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());

		List<Object> requestResponseBodyAdviceBeans = new ArrayList<>();

		for (ControllerAdviceBean adviceBean : adviceBeans) {
   
     
			Class<?> beanType = adviceBean.getBeanType();
			if (beanType == null) {
   
     
				throw new IllegalStateException("Unresolvable type for ControllerAdviceBean: " + adviceBean);
			}
			//获取@ModelAttribute注解的方法
			Set<Method> attrMethods = MethodIntrospector.selectMethods(beanType, MODEL_ATTRIBUTE_METHODS);
			if (!attrMethods.isEmpty()) {
   
     
				this.modelAttributeAdviceCache.put(adviceBean, attrMethods);
			}
			//获取@InitBinder注解的方法
			Set<Method> binderMethods = MethodIntrospector.selectMethods(beanType, INIT_BINDER_METHODS);
			if (!binderMethods.isEmpty()) {
   
     
				this.initBinderAdviceCache.put(adviceBean, binderMethods);
			}
			//是否实现了RequestBodyAdvice或ResponseBodyAdvice接口
			if (RequestBodyAdvice.class.isAssignableFrom(beanType) || ResponseBodyAdvice.class.isAssignableFrom(beanType)) {
   
     
				requestResponseBodyAdviceBeans.add(adviceBean);
			}
		}

		if (!requestResponseBodyAdviceBeans.isEmpty()) {
   
     
			this.requestResponseBodyAdvice.addAll(0, requestResponseBodyAdviceBeans);
		}

		if (logger.isDebugEnabled()) {
   
     
			int modelSize = this.modelAttributeAdviceCache.size();
			int binderSize = this.initBinderAdviceCache.size();
			int reqCount = getBodyAdviceCount(RequestBodyAdvice.class);
			int resCount = getBodyAdviceCount(ResponseBodyAdvice.class);
			if (modelSize == 0 && binderSize == 0 && reqCount == 0 && resCount == 0) {
   
     
				logger.debug("ControllerAdvice beans: none");
			}
			else {
   
     
				logger.debug("ControllerAdvice beans: " + modelSize + " @ModelAttribute, " + binderSize +
						" @InitBinder, " + reqCount + " RequestBodyAdvice, " + resCount + " ResponseBodyAdvice");
			}
		}
	}

三、获取Adapter

1、DispatcherServlet.getHandlerAdapter( )

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
   
     
		if (this.handlerAdapters != null) {
   
     
			for (HandlerAdapter adapter : this.handlerAdapters) {
   
     
				//遍历所有适配器,这里分析RequestMappingHandlerAdapter
				if (adapter.supports(handler)) {
   
     
					return adapter;
				}
			}
		}
		throw new ServletException("No adapter for handler [" + handler +
				"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
	}

2、RequestMappingHandlerAdapter.supports( )

public final boolean supports(Object handler) {
   
     
		//是HandlerMethod,并且调用子类supportsInternal,RequestMappingHandlerAdapter的supportsInternal方法返回true
		return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
	}

protected boolean supportsInternal(HandlerMethod handlerMethod) {
   
     
		return true;
	}

四、执行handler

接下来调用适配器的handler方法

1、AbstractHandlerMethodAdapter.handle( )

public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
   
     
		//回调子类的RequestMappingHandlerAdapter的handleInternal( )
		return handleInternal(request, response, (HandlerMethod) handler);
	}

2、RequestMappingHandlerAdapter.handleInternal( )

返回ModelAndView

protected ModelAndView handleInternal(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
   
     

		ModelAndView mav;
		//检查方法是否支持以及是否需要session
		checkRequest(request);

		// Execute invokeHandlerMethod in synchronized block if required.
		//同步
		if (this.synchronizeOnSession) {
   
     
			HttpSession session = request.getSession(false);
			if (session != null) {
   
     
				Object mutex = WebUtils.getSessionMutex(session);
				synchronized (mutex) {
   
     
					mav = invokeHandlerMethod(request, response, handlerMethod);
				}
			}
			else {
   
     
				// No HttpSession available -> no mutex necessary
				mav = invokeHandlerMethod(request, response, handlerMethod);
			}
		}
		else {
   
     
			// No synchronization on session demanded at all...
			//异步,返回ModelAndView 
			mav = invokeHandlerMethod(request, response, handlerMethod);
		}

		if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
   
     
			if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
   
     
				applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
			}
			else {
   
     
				prepareResponse(response);
			}
		}

		return mav;
	}

3、invokeHandlerMethod( )

	protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
   
     
		
		//包装请求和响应
		ServletWebRequest webRequest = new ServletWebRequest(request, response);
		try {
   
     
			//处理initBinderMethod
			WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
			ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
			
			//包装handlerMethod
			ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
			//设置参数解析器
			if (this.argumentResolvers != null) {
   
     
				invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
			}
			//设置返回值处理器
			if (this.returnValueHandlers != null) {
   
     
				invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
			}
			invocableMethod.setDataBinderFactory(binderFactory);
			//设置参数名发现器
			invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
			
			//ModelAndView容器
			ModelAndViewContainer mavContainer = new ModelAndViewContainer();
			mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
			modelFactory.initModel(webRequest, mavContainer, invocableMethod);
			mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);

			//异步请求处理
			AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
			asyncWebRequest.setTimeout(this.asyncRequestTimeout);

			WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
			asyncManager.setTaskExecutor(this.taskExecutor);
			asyncManager.setAsyncWebRequest(asyncWebRequest);
			asyncManager.registerCallableInterceptors(this.callableInterceptors);
			asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);

			if (asyncManager.hasConcurrentResult()) {
   
     
				Object result = asyncManager.getConcurrentResult();
				mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
				asyncManager.clearConcurrentResult();
				LogFormatUtils.traceDebug(logger, traceOn -> {
   
     
					String formatted = LogFormatUtils.formatValue(result, !traceOn);
					return "Resume with async result [" + formatted + "]";
				});
				invocableMethod = invocableMethod.wrapConcurrentResult(result);
			}
			
			//调用目标handler
			invocableMethod.invokeAndHandle(webRequest, mavContainer);
			if (asyncManager.isConcurrentHandlingStarted()) {
   
     
				return null;
			}
			
			//执行完获取ModelAndView
			return getModelAndView(mavContainer, modelFactory, webRequest);
		}
		finally {
   
     
			webRequest.requestCompleted();
		}
	}

4、invokeAndHandle( )

ServletInvocableHandlerMethod.java

public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {
   
     
		
		//执行invokeForRequest
		Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
		setResponseStatus(webRequest);

		if (returnValue == null) {
   
     
			if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {
   
     
				disableContentCachingIfNecessary(webRequest);
				mavContainer.setRequestHandled(true);
				return;
			}
		}
		else if (StringUtils.hasText(getResponseStatusReason())) {
   
     
			mavContainer.setRequestHandled(true);
			return;
		}

		mavContainer.setRequestHandled(false);
		Assert.state(this.returnValueHandlers != null, "No return value handlers");
		try {
   
     
			//调用返回值处理器处理结果
			this.returnValueHandlers.handleReturnValue(
					returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
		}
		catch (Exception ex) {
   
     
			if (logger.isTraceEnabled()) {
   
     
				logger.trace(formatErrorForReturnValue(returnValue), ex);
			}
			throw ex;
		}
	}

5、invokeForRequest( )

InvocableHandlerMethod.java

public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {
   
     
		
		//解析参数值
		Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
		if (logger.isTraceEnabled()) {
   
     
			logger.trace("Arguments: " + Arrays.toString(args));
		}
		//执行目标方法
		return doInvoke(args);
	}

6、getMethodArgumentValues( )

protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {
   
     
		
		//获取方法参数
		MethodParameter[] parameters = getMethodParameters();
		if (ObjectUtils.isEmpty(parameters)) {
   
     
			return EMPTY_ARGS;
		}

		Object[] args = new Object[parameters.length];
		for (int i = 0; i < parameters.length; i++) {
   
     
			MethodParameter parameter = parameters[i];
			parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
			args[i] = findProvidedArgument(parameter, providedArgs);
			if (args[i] != null) {
   
     
				continue;
			}
			//参数解析器支持该参数
			if (!this.resolvers.supportsParameter(parameter)) {
   
     
				throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver"));
			}
			try {
   
     
				//解析出参数
				args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
			}
			catch (Exception ex) {
   
     
				// Leave stack trace for later, exception may actually be resolved and handled...
				if (logger.isDebugEnabled()) {
   
     
					String exMsg = ex.getMessage();
					if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) {
   
     
						logger.debug(formatArgumentError(parameter, exMsg));
					}
				}
				throw ex;
			}
		}
		return args;
	}

解析完参数后,进行方法的调用

7、doInvoke( )

protected Object doInvoke(Object... args) throws Exception {
   
     
		Method method = getBridgedMethod();
		ReflectionUtils.makeAccessible(method);
		try {
   
     
			if (KotlinDetector.isSuspendingFunction(method)) {
   
     
				return CoroutinesUtils.invokeSuspendingFunction(method, getBean(), args);
			}
			//通过反射调用
			return method.invoke(getBean(), args);
		}

...
}

目标方法执行完毕,进入结果的处理

8、handleReturnValue( )

public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
			ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
   
     
		
		//找出合适的处理结果的handler
		HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType);
		if (handler == null) {
   
     
			throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());
		}
		//处理结果
		handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
	}

处理完结果,处理ModelAndView

9、getModelAndView( )

private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,
			ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {
   
     

		modelFactory.updateModel(webRequest, mavContainer);
		if (mavContainer.isRequestHandled()) {
   
     
			return null;
		}
		ModelMap model = mavContainer.getModel();
		ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus());
		if (!mavContainer.isViewReference()) {
   
     
			mav.setView((View) mavContainer.getView());
		}
		if (model instanceof RedirectAttributes) {
   
     
			Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes();
			HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
			if (request != null) {
   
     
				RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
			}
		}
		return mav;
	}

}