springmvc组件HandlerAdapter源码-AbstractHandlerMethodAdapter

/*
 * Copyright 2002-2019 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.web.servlet.mvc.method.annotation;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.MethodIntrospector;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.core.ReactiveAdapterRegistry;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.core.log.LogFormatUtils;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter;
import org.springframework.http.converter.xml.SourceHttpMessageConverter;
import org.springframework.lang.Nullable;
import org.springframework.ui.ModelMap;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ReflectionUtils.MethodFilter;
import org.springframework.web.accept.ContentNegotiationManager;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.support.*;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.context.request.async.*;
import org.springframework.web.method.ControllerAdviceBean;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.method.annotation.*;
import org.springframework.web.method.support.*;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.mvc.annotation.ModelAndViewResolver;
import org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import org.springframework.web.servlet.support.RequestContextUtils;
import org.springframework.web.util.WebUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 支持的 {@link AbstractHandlerMethodAdapter} 扩展
 * {@link RequestMapping @RequestMapping} 注释为 {@link HandlerMethod HandlerMethods}。
 *
 * <p>可以通过添加对自定义参数和返回值类型的支持
 * {@link #setCustomArgumentResolvers} 和 {@link #setCustomReturnValueHandlers},
 * 或者,重新配置所有参数和返回值类型,
 * 使用 {@link #setArgumentResolvers} 和 {@link #setReturnValueHandlers}。
 *
 * @author Rossen Stoyanchev
 * @author Juergen Hoeller
 * @see HandlerMethodArgumentResolver
 * @see HandlerMethodReturnValueHandler
 * @since 3.1
 */
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
		implements BeanFactoryAware, InitializingBean {

	/**
	 * MethodFilter 匹配 {@link InitBinder @InitBinder} 方法。
	 */
	public static final MethodFilter INIT_BINDER_METHODS = method ->
			AnnotatedElementUtils.hasAnnotation(method, InitBinder.class);

	/**
	 * MethodFilter 匹配 {@link ModelAttribute @ModelAttribute} 方法。
	 */
	public static final MethodFilter MODEL_ATTRIBUTE_METHODS = method ->
			(!AnnotatedElementUtils.hasAnnotation(method, RequestMapping.class) &&
					AnnotatedElementUtils.hasAnnotation(method, ModelAttribute.class));


	@Nullable
	private List<HandlerMethodArgumentResolver> customArgumentResolvers;

	@Nullable
	private HandlerMethodArgumentResolverComposite argumentResolvers;

	@Nullable
	private HandlerMethodArgumentResolverComposite initBinderArgumentResolvers;

	@Nullable
	private List<HandlerMethodReturnValueHandler> customReturnValueHandlers;

	@Nullable
	private HandlerMethodReturnValueHandlerComposite returnValueHandlers;

	@Nullable
	private List<ModelAndViewResolver> modelAndViewResolvers;

	private ContentNegotiationManager contentNegotiationManager = new ContentNegotiationManager();

	private List<HttpMessageConverter<?>> messageConverters;

	private List<Object> requestResponseBodyAdvice = new ArrayList<>();

	@Nullable
	private WebBindingInitializer webBindingInitializer;

	private AsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor("MvcAsync");

	@Nullable
	private Long asyncRequestTimeout;

	private CallableProcessingInterceptor[] callableInterceptors = new CallableProcessingInterceptor[0];

	private DeferredResultProcessingInterceptor[] deferredResultInterceptors = new DeferredResultProcessingInterceptor[0];

	private ReactiveAdapterRegistry reactiveAdapterRegistry = ReactiveAdapterRegistry.getSharedInstance();

	private boolean ignoreDefaultModelOnRedirect = false;

	private int cacheSecondsForSessionAttributeHandlers = 0;

	private boolean synchronizeOnSession = false;

	private SessionAttributeStore sessionAttributeStore = new DefaultSessionAttributeStore();

	private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();

	@Nullable
	private ConfigurableBeanFactory beanFactory;


	private final Map<Class<?>, SessionAttributesHandler> sessionAttributesHandlerCache = new ConcurrentHashMap<>(64);

	private final Map<Class<?>, Set<Method>> initBinderCache = new ConcurrentHashMap<>(64);

	private final Map<ControllerAdviceBean, Set<Method>> initBinderAdviceCache = new LinkedHashMap<>();

	private final Map<Class<?>, Set<Method>> modelAttributeCache = new ConcurrentHashMap<>(64);

	private final Map<ControllerAdviceBean, Set<Method>> modelAttributeAdviceCache = new LinkedHashMap<>();


	public RequestMappingHandlerAdapter() {
		this.messageConverters = new ArrayList<>(4);
		this.messageConverters.add(new ByteArrayHttpMessageConverter());
		this.messageConverters.add(new StringHttpMessageConverter());
		try {
			this.messageConverters.add(new SourceHttpMessageConverter<>());
		} catch (Error err) {
			// Ignore when no TransformerFactory implementation is available
		}
		this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());
	}


	/**
	 * 为自定义参数类型提供解析器。自定义解析器已订购
	 * 在内置的之后。覆盖对参数的内置支持
	 * 解析使用 {@link #setArgumentResolvers} 代替。
	 */
	public void setCustomArgumentResolvers(@Nullable List<HandlerMethodArgumentResolver> argumentResolvers) {
		this.customArgumentResolvers = argumentResolvers;
	}

	/**
	 * 返回自定义参数解析器,或 {@code null}。
	 */
	@Nullable
	public List<HandlerMethodArgumentResolver> getCustomArgumentResolvers() {
		return this.customArgumentResolvers;
	}

	/**
	 * 配置支持的参数类型的完整列表,从而覆盖
	 * 否则默认配置的解析器。
	 */
	public void setArgumentResolvers(@Nullable List<HandlerMethodArgumentResolver> argumentResolvers) {
		if (argumentResolvers == null) {
			this.argumentResolvers = null;
		} else {
			this.argumentResolvers = new HandlerMethodArgumentResolverComposite();
			this.argumentResolvers.addResolvers(argumentResolvers);
		}
	}

	/**
	 * 返回配置的参数解析器,或者可能 {@code null} 如果
	 * 尚未通过 {@link #afterPropertiesSet()} 初始化。
	 */
	@Nullable
	public List<HandlerMethodArgumentResolver> getArgumentResolvers() {
		return (this.argumentResolvers != null ? this.argumentResolvers.getResolvers() : null);
	}

	/**
	 * 在 {@code @InitBinder} 方法中配置支持的参数类型。
	 */
	public void setInitBinderArgumentResolvers(@Nullable List<HandlerMethodArgumentResolver> argumentResolvers) {
		if (argumentResolvers == null) {
			this.initBinderArgumentResolvers = null;
		} else {
			this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite();
			this.initBinderArgumentResolvers.addResolvers(argumentResolvers);
		}
	}

	/**
	 * 返回 {@code @InitBinder} 方法的参数解析器,或者可能
	 * {@code null} 如果尚未通过 {@link #afterPropertiesSet()} 初始化。
	 */
	@Nullable
	public List<HandlerMethodArgumentResolver> getInitBinderArgumentResolvers() {
		return (this.initBinderArgumentResolvers != null ? this.initBinderArgumentResolvers.getResolvers() : null);
	}

	/**
	 * 为自定义返回值类型提供处理程序。自定义处理程序是
	 * 在内置的之后排序。覆盖对内置的支持
	 * 返回值处理使用 {@link #setReturnValueHandlers}。
	 */
	public void setCustomReturnValueHandlers(@Nullable List<HandlerMethodReturnValueHandler> returnValueHandlers) {
		this.customReturnValueHandlers = returnValueHandlers;
	}

	/**
	 * 返回自定义返回值处理程序,或 {@code null}.
	 */
	@Nullable
	public List<HandlerMethodReturnValueHandler> getCustomReturnValueHandlers() {
		return this.customReturnValueHandlers;
	}

	/**
	 * C配置支持的返回值类型的完整列表,从而*覆盖默认情况下会配置的处理程序。
	 */
	public void setReturnValueHandlers(@Nullable List<HandlerMethodReturnValueHandler> returnValueHandlers) {
		if (returnValueHandlers == null) {
			this.returnValueHandlers = null;
		} else {
			this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite();
			this.returnValueHandlers.addHandlers(returnValueHandlers);
		}
	}

	/**
	 * 返回配置的处理程序,如果没有,则可能返回 {@code null}
	 * 尚未通过 {@link #afterPropertiesSet()} 初始化。
	 */
	@Nullable
	public List<HandlerMethodReturnValueHandler> getReturnValueHandlers() {
		return (this.returnValueHandlers != null ? this.returnValueHandlers.getHandlers() : null);
	}

	/**
	 * 提供自定义 {@link ModelAndViewResolver ModelAndViewResolvers}。
	 * <p><strong>注意:</strong>此方法可用于向后
	 * 仅兼容性。但是,建议重新编写一个
	 * {@code ModelAndViewResolver} 作为 {@link HandlerMethodReturnValueHandler}。
	 * 两个接口之间的适配器是不可能的,因为
	 * {@link HandlerMethodReturnValueHandler#supportsReturnType} 方法
	 * 无法实现。因此 {@code ModelAndViewResolver} 是有限的
	 * 在所有其他返回值之后总是在最后被调用
	 * 处理程序有机会。
	 * <p>{@code HandlerMethodReturnValueHandler} 提供更好的访问
	 * 返回类型和控制器方法信息并可以订购
	 * 相对于其他返回值处理程序自由。
	 */
	public void setModelAndViewResolvers(@Nullable List<ModelAndViewResolver> modelAndViewResolvers) {
		this.modelAndViewResolvers = modelAndViewResolvers;
	}

	/**
	 * 返回配置好的{@link ModelAndViewResolver ModelAndViewResolvers},或者{@code null}。
	 */
	@Nullable
	public List<ModelAndViewResolver> getModelAndViewResolvers() {
		return this.modelAndViewResolvers;
	}

	/**
	 * 设置 {@link ContentNegotiationManager} 以用于确定请求的媒体类型。
	 * 如果未设置,则使用默认构造函数。
	 */
	public void setContentNegotiationManager(ContentNegotiationManager contentNegotiationManager) {
		this.contentNegotiationManager = contentNegotiationManager;
	}

	/**
	 * 提供用于参数解析器和返回值的转换器
	 * 支持读取和/或写入主体的处理程序
	 * 请求和响应。
	 */
	public void setMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
		this.messageConverters = messageConverters;
	}

	/**
	 * 返回配置的消息正文转换器。
	 */
	public List<HttpMessageConverter<?>> getMessageConverters() {
		return this.messageConverters;
	}

	/**
	 * 添加一个或多个 {@code RequestBodyAdvice} 实例来拦截
	 * 在它被读取和转换为 {@code @RequestBody} 之前请求和
	 * {@code HttpEntity} 方法参数。
	 */
	public void setRequestBodyAdvice(@Nullable List<RequestBodyAdvice> requestBodyAdvice) {
		if (requestBodyAdvice != null) {
			this.requestResponseBodyAdvice.addAll(requestBodyAdvice);
		}
	}

	/**
	 * 添加一个或多个 {@code ResponseBodyAdvice} 实例来拦截
	 * {@code @ResponseBody} 或 {@code ResponseEntity} 返回之前的响应
	 * 值被写入响应正文。
	 */
	public void setResponseBodyAdvice(@Nullable List<ResponseBodyAdvice<?>> responseBodyAdvice) {
		if (responseBodyAdvice != null) {
			this.requestResponseBodyAdvice.addAll(responseBodyAdvice);
		}
	}

	/**
	 * 提供具有“全局”初始化的 WebBindingInitializer 以应用
	 * 到每个 DataBinder 实例。
	 */
	public void setWebBindingInitializer(@Nullable WebBindingInitializer webBindingInitializer) {
		this.webBindingInitializer = webBindingInitializer;
	}

	/**
	 * 返回配置的 WebBindingInitializer,如果没有,则返回 {@code null}。
	 */
	@Nullable
	public WebBindingInitializer getWebBindingInitializer() {
		return this.webBindingInitializer;
	}

	/**
	 * 设置默认 {@link AsyncTaskExecutor} 以在控制器方法
	 * 返回一个 {@link Callable}。控制器方法可以覆盖此默认值
	 * 通过返回 {@link WebAsyncTask} 以每个请求为基础。
	 * <p>默认使用 {@link SimpleAsyncTaskExecutor} 实例。
	 * 建议将生产中的默认设置更改为简单的执行程序
	 * 不重复使用线程。
	 */
	public void setTaskExecutor(AsyncTaskExecutor taskExecutor) {
		this.taskExecutor = taskExecutor;
	}

	/**
	 * 指定并发处理之前的时间量(以毫秒为单位)
	 * 应该超时。在 Servlet 3 中,超时从主请求之后开始
	 * 处理线程已退出并在请求再次分派时结束
	 * 用于进一步处理同时产生的结果。
	 * <p>如果没有设置这个值,底层的默认超时时间
	 * 使用实现,例如使用 Servlet 3 在 Tomcat 上运行 10 秒。
	 *
	 * @param timeout the timeout value in milliseconds
	 */
	public void setAsyncRequestTimeout(long timeout) {
		this.asyncRequestTimeout = timeout;
	}

	/**
	 * 配置 {@code CallableProcessingInterceptor} 以注册异步请求.
	 *
	 * @param interceptors the interceptors to register
	 */
	public void setCallableInterceptors(List<CallableProcessingInterceptor> interceptors) {
		this.callableInterceptors = interceptors.toArray(new CallableProcessingInterceptor[0]);
	}

	/**
	 * 配置 {@code DeferredResultProcessingInterceptor} 以注册异步请求。
	 *
	 * @param interceptors the interceptors to register
	 */
	public void setDeferredResultInterceptors(List<DeferredResultProcessingInterceptor> interceptors) {
		this.deferredResultInterceptors = interceptors.toArray(new DeferredResultProcessingInterceptor[0]);
	}

	/**
	 * 为要支持的反应库类型配置注册表
	 * 从控制器方法返回值。
	 *
	 * @since 5.0.5
	 */
	public void setReactiveAdapterRegistry(ReactiveAdapterRegistry reactiveAdapterRegistry) {
		this.reactiveAdapterRegistry = reactiveAdapterRegistry;
	}

	/**
	 * 返回已配置的适配器反应类型注册表。
	 *
	 * @since 5.0
	 */
	public ReactiveAdapterRegistry getReactiveAdapterRegistry() {
		return this.reactiveAdapterRegistry;
	}

	/**
	 * 默认情况下,“默认”模型的内容在
	 * 渲染和重定向场景。或者控制器方法
	 * 可以声明一个 {@link RedirectAttributes} 参数并使用它来提供
	 * 重定向的属性。
	 * <p>将此标志设置为 {@code true} 保证“默认”模型为
	 * 从未在重定向场景中使用,即使 RedirectAttributes 参数
	 * 未声明。将其设置为 {@code false} 表示“默认”模型
	 * 如果控制器方法没有声明
	 * RedirectAttributes 参数。
	 * <p>默认设置是 {@code false} 但新的应用程序应该
	 * 考虑将其设置为 {@code true}。
	 *
	 * @see RedirectAttributes
	 */
	public void setIgnoreDefaultModelOnRedirect(boolean ignoreDefaultModelOnRedirect) {
		this.ignoreDefaultModelOnRedirect = ignoreDefaultModelOnRedirect;
	}

	/**
	 * 指定用于存储会话属性的策略。默认是
	 * {@link org.springframework.web.bind.support.DefaultSessionAttributeStore},
	 * 在具有相同属性的 HttpSession 中存储会话属性
	 * 模型中的名称。
	 */
	public void setSessionAttributeStore(SessionAttributeStore sessionAttributeStore) {
		this.sessionAttributeStore = sessionAttributeStore;
	}

	/**
	 * 缓存由 {@code @SessionAttributes} 注释处理程序生成的内容
	 * 对于给定的秒数。
	 * <p>可能的值是:
	 * <ul>
	 * <li>-1:不生成缓存相关的头</li>
	 * <li>0 (默认值): "Cache-Control: no-store" 将阻止缓存</li>
	 * <li>1 或更高:"Cache-Control: max-age=seconds" 会要求缓存内容;
	 * 处理会话属性时不建议</li>
	 * </ul>
	 * <p>与“cacheSeconds”属性相反,它适用于所有一般
	 * 处理程序(但不是 {@code @SessionAttributes} 注释处理程序),
	 * 此设置仅适用于 {@code @SessionAttributes} 处理程序。
	 *
	 * @see #setCacheSeconds
	 * @see org.springframework.web.bind.annotation.SessionAttributes
	 */
	public void setCacheSecondsForSessionAttributeHandlers(int cacheSecondsForSessionAttributeHandlers) {
		this.cacheSecondsForSessionAttributeHandlers = cacheSecondsForSessionAttributeHandlers;
	}

	/**
	 * 设置控制器执行是否应该在会话上同步,
	 * 序列化来自同一客户端的并行调用。
	 * <p>更具体地说,{@code handleRequestInternal} 的执行
	 * 如果此标志为“true”,方法将同步。最好的
	 * 会话互斥将用于同步;理想情况下,这将
	 * 是 HttpSessionMutexListener 公开的互斥锁。
	 * <p>会话互斥量保证是同一个对象
	 * 会话的整个生命周期,在定义的键下可用
	 * 通过 {@code SESSION_MUTEX_ATTRIBUTE} 常量。它作为一个
	 * 安全参考同步锁定当前会话。
	 * <p>在很多情况下,HttpSession 引用本身就是一个安全的互斥锁
	 * 也是如此,因为它始终是相同的对象引用
	 * 相同的活动逻辑会话。但是,这并不能保证
	 * 不同的servlet容器;唯一 100% 安全的方法是会话互斥锁。
	 *
	 * @see org.springframework.web.util.HttpSessionMutexListener
	 * @see org.springframework.web.util.WebUtils#getSessionMutex(javax.servlet.http.HttpSession)
	 */
	public void setSynchronizeOnSession(boolean synchronizeOnSession) {
		this.synchronizeOnSession = synchronizeOnSession;
	}

	/**
	 * 设置 ParameterNameDiscoverer 以在需要时用于解析方法参数名称
	 * (例如对于默认属性名称)。
	 * <p>Default is a {@link org.springframework.core.DefaultParameterNameDiscoverer}.
	 */
	public void setParameterNameDiscoverer(ParameterNameDiscoverer parameterNameDiscoverer) {
		this.parameterNameDiscoverer = parameterNameDiscoverer;
	}

	/**
	 * 解析表达式需要一个 {@link ConfigurableBeanFactory}
	 * 在方法参数默认值中。
	 */
	@Override
	public void setBeanFactory(BeanFactory beanFactory) {
		if (beanFactory instanceof ConfigurableBeanFactory) {
			this.beanFactory = (ConfigurableBeanFactory) beanFactory;
		}
	}

	/**
	 * 返回此 bean 实例的拥有工厂,如果没有,则返回 {@code null}。
	 */
	@Nullable
	protected ConfigurableBeanFactory getBeanFactory() {
		return this.beanFactory;
	}


	@Override
	public void afterPropertiesSet() {
		// 首先这样做,它可能会添加 ResponseBody 建议 bean
		//加载加了ControllerAdvice注解的类
		initControllerAdviceCache();
		//参数解析为空,加载默认的参数解析类
		if (this.argumentResolvers == null) {
			List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
			this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
		}
		//参数解析为空,加载默认的初始化参数绑定类
		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);
		}
	}

	private void initControllerAdviceCache() {
		if (getApplicationContext() == null) {
			return;
		}
		//处理加了ControllerAdvice注解的类
		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);
			}
			//查找bean中没有加RequestMapping注解,加了ModelAttribute注解的方法
			Set<Method> attrMethods = MethodIntrospector.selectMethods(beanType, MODEL_ATTRIBUTE_METHODS);
			if (!attrMethods.isEmpty()) {
				//缓存加了ModelAttribute方法
				this.modelAttributeAdviceCache.put(adviceBean, attrMethods);
			}
			//查找bean中加了InitBinder注解的方法
			Set<Method> binderMethods = MethodIntrospector.selectMethods(beanType, INIT_BINDER_METHODS);
			if (!binderMethods.isEmpty()) {
				//缓存ModelAttribute注解的方法
				this.initBinderAdviceCache.put(adviceBean, binderMethods);
			}
			//bean类型的父类是RequestBodyAdvice或者ResponseBodyAdvice添加进requestResponseBodyAdviceBeans里
			if (RequestBodyAdvice.class.isAssignableFrom(beanType) || ResponseBodyAdvice.class.isAssignableFrom(beanType)) {
				requestResponseBodyAdviceBeans.add(adviceBean);
			}
		}
		//设置requestResponseBodyAdviceBeans到requestResponseBodyAdvice属性
		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");
			}
		}
	}

	// Count all advice, including explicit registrations..

	private int getBodyAdviceCount(Class<?> adviceType) {
		List<Object> advice = this.requestResponseBodyAdvice;
		return RequestBodyAdvice.class.isAssignableFrom(adviceType) ?
				RequestResponseBodyAdviceChain.getAdviceByType(advice, RequestBodyAdvice.class).size() :
				RequestResponseBodyAdviceChain.getAdviceByType(advice, ResponseBodyAdvice.class).size();
	}

	/**
	 * 返回要使用的参数解析器列表,包括内置解析器
	 * 和通过 {@link #setCustomArgumentResolvers} 提供的自定义解析器。
	 */
	private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
		List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>();

		// 基于注释的参数解析
		//解析加了RequestParam注解的参数
		resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
		//解析加了RequestParamMap注解的参数
		resolvers.add(new RequestParamMapMethodArgumentResolver());
		//解析加了PathVariable注解的参数
		resolvers.add(new PathVariableMethodArgumentResolver());
		//解析加了PathVariable注解的map
		resolvers.add(new PathVariableMapMethodArgumentResolver());
		//解析加了MatrixVariable注解的参数
		resolvers.add(new MatrixVariableMethodArgumentResolver());
		//解析加了MatrixVariable注解的map参数
		resolvers.add(new MatrixVariableMapMethodArgumentResolver());
		//
		resolvers.add(new ServletModelAttributeMethodProcessor(false));
		//解析加了RequestBody或加了ResponseBody注解的参数或方法
		resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
		//解析RequestPart注解的参数
		resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters(), this.requestResponseBodyAdvice));
		//解析加了RequestHeader注解的参数
		resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));
		//解析加了RequestHeader注解的map参数
		resolvers.add(new RequestHeaderMapMethodArgumentResolver());
		//解析HttpServletRequest的cookie值
		resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory()));
		//解析加了Value注解的参数
		resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
		//解析加了SessionAttribute的参数
		resolvers.add(new SessionAttributeMethodArgumentResolver());
		//解析加了RequestAttribute的参数
		resolvers.add(new RequestAttributeMethodArgumentResolver());

		// 基于类型的参数解析
		//解析 servlet 支持的与请求相关的方法参数
		resolvers.add(new ServletRequestMethodArgumentResolver());
		//解析 servlet 支持的响应相关方法参数
		resolvers.add(new ServletResponseMethodArgumentResolver());
		//解析 {@link HttpEntity} 和 {@link RequestEntity} 方法参数值
		//并且还处理 {@link HttpEntity} 和 {@link ResponseEntity} 返回值。
		resolvers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
		//解析加了RedirectAttributes注解的参数
		resolvers.add(new RedirectAttributesMethodArgumentResolver());
		//解析model参数,并处理Model返回值
		resolvers.add(new ModelMethodProcessor());
		//解析map参数并处理map返回值
		resolvers.add(new MapMethodProcessor());
		//解析错误返回信息,BindingResult
		resolvers.add(new ErrorsMethodArgumentResolver());
		//解析SessionStatus参数
		resolvers.add(new SessionStatusMethodArgumentResolver());
		//解析UriComponentsBuilder类型的参数
		resolvers.add(new UriComponentsBuilderMethodArgumentResolver());

		// 自定义参数解析
		if (getCustomArgumentResolvers() != null) {
			resolvers.addAll(getCustomArgumentResolvers());
		}

		//包罗万象
		resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
		resolvers.add(new ServletModelAttributeMethodProcessor(true));

		return resolvers;
	}

	/**
	 * 返回用于 {@code @InitBinder} 的参数解析器列表
	 * 包括内置和自定义解析器的方法。
	 */
	private List<HandlerMethodArgumentResolver> getDefaultInitBinderArgumentResolvers() {
		List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>();

		// 基于注释的参数解析
		resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
		resolvers.add(new RequestParamMapMethodArgumentResolver());
		resolvers.add(new PathVariableMethodArgumentResolver());
		resolvers.add(new PathVariableMapMethodArgumentResolver());
		resolvers.add(new MatrixVariableMethodArgumentResolver());
		resolvers.add(new MatrixVariableMapMethodArgumentResolver());
		resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
		resolvers.add(new SessionAttributeMethodArgumentResolver());
		resolvers.add(new RequestAttributeMethodArgumentResolver());

		// 基于类型的参数解析
		resolvers.add(new ServletRequestMethodArgumentResolver());
		resolvers.add(new ServletResponseMethodArgumentResolver());

		//自定义参数
		if (getCustomArgumentResolvers() != null) {
			resolvers.addAll(getCustomArgumentResolvers());
		}

		// 包罗万象
		resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));

		return resolvers;
	}

	/**
	 * 返回要使用的返回值处理程序列表,包括内置和
	 * 通过 {@link #setReturnValueHandlers} 提供的自定义处理程序。
	 */
	private List<HandlerMethodReturnValueHandler> getDefaultReturnValueHandlers() {
		List<HandlerMethodReturnValueHandler> handlers = new ArrayList<>();

		// 单一用途的返回值类型
		//加载返回值类型是ModelAndView的处理器
		handlers.add(new ModelAndViewMethodReturnValueHandler());
		//加载model类型的返回值的处理器
		handlers.add(new ModelMethodProcessor());
		//加载返回值类型是View的处理器
		handlers.add(new ViewMethodReturnValueHandler());
		//加载ResponseBodyEmitter返回值类型的处理器
		handlers.add(new ResponseBodyEmitterReturnValueHandler(getMessageConverters(),
				this.reactiveAdapterRegistry, this.taskExecutor, this.contentNegotiationManager));
		//加载StreamingResponseBody类型的处理器
		handlers.add(new StreamingResponseBodyReturnValueHandler());
		//加载处理HttpEntity和ResponseEntity返回值的处理器
		handlers.add(new HttpEntityMethodProcessor(getMessageConverters(),
				this.contentNegotiationManager, this.requestResponseBodyAdvice));
		//加载HttpHeaders返回值的处理器
		handlers.add(new HttpHeadersReturnValueHandler());
		//加载Callable类型返回值的处理器
		handlers.add(new CallableMethodReturnValueHandler());
		//加载DeferredResult类型返回值的处理器
		handlers.add(new DeferredResultMethodReturnValueHandler());
		//处理WebAsyncTask返回值类型的处理器
		handlers.add(new AsyncTaskMethodReturnValueHandler(this.beanFactory));

		// 基于注解的返回值类型
		//解析加了ModelAttribute注解的处理器
		handlers.add(new ModelAttributeMethodProcessor(false));
		//解析加了ResponseBody的处理器
		handlers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(),
				this.contentNegotiationManager, this.requestResponseBodyAdvice));

		// 多用途返回值类型
		//加载处理类型是void或String处理器
		handlers.add(new ViewNameMethodReturnValueHandler());
		//加载返回值是map的处理器
		handlers.add(new MapMethodProcessor());

		// 自定义返回值类型
		if (getCustomReturnValueHandlers() != null) {
			handlers.addAll(getCustomReturnValueHandlers());
		}

		//包罗万象
		if (!CollectionUtils.isEmpty(getModelAndViewResolvers())) {
			handlers.add(new ModelAndViewResolverMethodReturnValueHandler(getModelAndViewResolvers()));
		} else {
			handlers.add(new ModelAttributeMethodProcessor(true));
		}

		return handlers;
	}


	/**
	 * 始终返回 {@code true},因为任何方法参数和返回值
	 * 类型会以某种方式进行处理。无法识别方法参数
	 * 被任何 HandlerMethodArgumentResolver 解释为请求参数
	 * 如果它是简单类型,否则作为模型属性。一个返回值
	 * 不被任何 HandlerMethodReturnValueHandler 识别的将被解释
	 * 作为模型属性。
	 */
	@Override
	protected boolean supportsInternal(HandlerMethod handlerMethod) {
		return true;
	}

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

		ModelAndView mav;
		//检查是否支持此请求方法
		checkRequest(request);

		// 如果需要,在同步块中执行 invokeHandlerMethod。
		if (this.synchronizeOnSession) {
			HttpSession session = request.getSession(false);
			if (session != null) {
				Object mutex = WebUtils.getSessionMutex(session);
				synchronized (mutex) {
					mav = invokeHandlerMethod(request, response, handlerMethod);
				}
			} else {
				//没有可用的 HttpSession -> 不需要互斥量
				mav = invokeHandlerMethod(request, response, handlerMethod);
			}
		} else {
			//根本不需要会话同步...
			mav = invokeHandlerMethod(request, response, handlerMethod);
		}
		//返回值中有Cache-Control的header参数
		if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
			//session属性处理器处理
			if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
				applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
			} else {
				prepareResponse(response);
			}
		}

		return mav;
	}

	/**
	 * 此实现始终返回 -1。 {@code @RequestMapping} 方法可以
	 * 计算lastModified值,调用{@link WebRequest#checkNotModified(long)},
	 * 如果调用的结果是 {@code true},则返回 {@code null}。
	 */
	@Override
	protected long getLastModifiedInternal(HttpServletRequest request, HandlerMethod handlerMethod) {
		return -1;
	}


	/**
	 * 返回给定处理程序类型的 {@link SessionAttributesHandler} 实例
	 * (从不{@code null})。
	 */
	private SessionAttributesHandler getSessionAttributesHandler(HandlerMethod handlerMethod) {
		Class<?> handlerType = handlerMethod.getBeanType();
		SessionAttributesHandler sessionAttrHandler = this.sessionAttributesHandlerCache.get(handlerType);
		if (sessionAttrHandler == null) {
			synchronized (this.sessionAttributesHandlerCache) {
				sessionAttrHandler = this.sessionAttributesHandlerCache.get(handlerType);
				if (sessionAttrHandler == null) {
					sessionAttrHandler = new SessionAttributesHandler(handlerType, this.sessionAttributeStore);
					this.sessionAttributesHandlerCache.put(handlerType, sessionAttrHandler);
				}
			}
		}
		return sessionAttrHandler;
	}

	/**
	 * 调用 {@link RequestMapping} 处理程序方法准备 {@link ModelAndView}
	 * 如果需要视图分辨率。
	 *
	 * @see #createInvocableHandlerMethod(HandlerMethod)
	 * @since 4.2
	 */
	@Nullable
	protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
											   HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

		//创建ServletWebRequest
		ServletWebRequest webRequest = new ServletWebRequest(request, response);
		try {
			//获取默认的处理WebDataBinder的工厂
			WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
			//获取处理model的工厂
			ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
			//根据当前处理方法,创建ServletInvocableHandlerMethod
			ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
			if (this.argumentResolvers != null) {
				//设置参数解析器
				invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
			}
			if (this.returnValueHandlers != null) {
				//设置返回值解析器
				invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
			}
			//设置处理WebDataBinder的工厂
			invocableMethod.setDataBinderFactory(binderFactory);
			invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);

			//创建
			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);
			}
			//执行请求方法处理
			invocableMethod.invokeAndHandle(webRequest, mavContainer);
			if (asyncManager.isConcurrentHandlingStarted()) {
				return null;
			}
			//获取ModelAndView
			return getModelAndView(mavContainer, modelFactory, webRequest);
		} finally {
			webRequest.requestCompleted();
		}
	}

	/**
	 * 从给定的 {@link HandlerMethod} 定义创建一个 {@link ServletInvocableHandlerMethod}。
	 *
	 * @param handlerMethod the {@link HandlerMethod} definition
	 * @return the corresponding {@link ServletInvocableHandlerMethod} (or custom subclass thereof)
	 * @since 4.2
	 */
	protected ServletInvocableHandlerMethod createInvocableHandlerMethod(HandlerMethod handlerMethod) {
		return new ServletInvocableHandlerMethod(handlerMethod);
	}

	private ModelFactory getModelFactory(HandlerMethod handlerMethod, WebDataBinderFactory binderFactory) {
		SessionAttributesHandler sessionAttrHandler = getSessionAttributesHandler(handlerMethod);
		Class<?> handlerType = handlerMethod.getBeanType();
		Set<Method> methods = this.modelAttributeCache.get(handlerType);
		if (methods == null) {
			methods = MethodIntrospector.selectMethods(handlerType, MODEL_ATTRIBUTE_METHODS);
			this.modelAttributeCache.put(handlerType, methods);
		}
		List<InvocableHandlerMethod> attrMethods = new ArrayList<>();
		// Global methods first
		this.modelAttributeAdviceCache.forEach((clazz, methodSet) -> {
			if (clazz.isApplicableToBeanType(handlerType)) {
				Object bean = clazz.resolveBean();
				for (Method method : methodSet) {
					attrMethods.add(createModelAttributeMethod(binderFactory, bean, method));
				}
			}
		});
		for (Method method : methods) {
			Object bean = handlerMethod.getBean();
			attrMethods.add(createModelAttributeMethod(binderFactory, bean, method));
		}
		return new ModelFactory(attrMethods, binderFactory, sessionAttrHandler);
	}

	private InvocableHandlerMethod createModelAttributeMethod(WebDataBinderFactory factory, Object bean, Method method) {
		InvocableHandlerMethod attrMethod = new InvocableHandlerMethod(bean, method);
		if (this.argumentResolvers != null) {
			attrMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
		}
		attrMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
		attrMethod.setDataBinderFactory(factory);
		return attrMethod;
	}

	private WebDataBinderFactory getDataBinderFactory(HandlerMethod handlerMethod) throws Exception {
		Class<?> handlerType = handlerMethod.getBeanType();
		Set<Method> methods = this.initBinderCache.get(handlerType);
		if (methods == null) {
			methods = MethodIntrospector.selectMethods(handlerType, INIT_BINDER_METHODS);
			this.initBinderCache.put(handlerType, methods);
		}
		List<InvocableHandlerMethod> initBinderMethods = new ArrayList<>();
		// Global methods first
		this.initBinderAdviceCache.forEach((clazz, methodSet) -> {
			if (clazz.isApplicableToBeanType(handlerType)) {
				Object bean = clazz.resolveBean();
				for (Method method : methodSet) {
					initBinderMethods.add(createInitBinderMethod(bean, method));
				}
			}
		});
		for (Method method : methods) {
			Object bean = handlerMethod.getBean();
			initBinderMethods.add(createInitBinderMethod(bean, method));
		}
		return createDataBinderFactory(initBinderMethods);
	}

	private InvocableHandlerMethod createInitBinderMethod(Object bean, Method method) {
		InvocableHandlerMethod binderMethod = new InvocableHandlerMethod(bean, method);
		if (this.initBinderArgumentResolvers != null) {
			binderMethod.setHandlerMethodArgumentResolvers(this.initBinderArgumentResolvers);
		}
		binderMethod.setDataBinderFactory(new DefaultDataBinderFactory(this.webBindingInitializer));
		binderMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
		return binderMethod;
	}

	/**
	 * 创建新的 InitBinderDataBinderFactory 实例的模板方法。
	 * <p>默认实现创建了一个 ServletRequestDataBinderFactory。
	 * 这可以被自定义 ServletRequestDataBinder 子类覆盖。
	 *
	 * @param binderMethods {@code @InitBinder} methods
	 * @return the InitBinderDataBinderFactory instance to use
	 * @throws Exception in case of invalid state or arguments
	 */
	protected InitBinderDataBinderFactory createDataBinderFactory(List<InvocableHandlerMethod> binderMethods)
			throws Exception {

		return new ServletRequestDataBinderFactory(binderMethods, getWebBindingInitializer());
	}

	@Nullable
	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;
	}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LouD_dm

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值