Spring mvc 之 HandlerAdapter 源码解析
HandlerAdapter 组件
HandlerAdapter 处理器的适配器,因为spring mvc中的处理器是多变的,我们可以通过实现Controller或者HttpRequestHandler接口,也可以通过@RequestMapping注解将方法作为一个处理器,这就导致spring mvc不能直接处理handler,所以这时候就需要一个适配器,让他去执行处理
HandlerAdapter组件之HandlerAdapter接口
public interface HandlerAdapter { //判断当前适配器是否支持该处理器 boolean supports(Object var1); //执行Handler @Nullable ModelAndView handle(HttpServletRequest var1, HttpServletResponse var2, Object var3) throws Exception; //返回请求最新的更新时间,如果不支持返回-1即可 long getLastModified(HttpServletRequest var1, Object var2); }复制代码
HandlerAdapter接口总共只有三个方法,相对于来说还是很好理解
supports方法就是判断当前适配器是否支持该处理器,因为handler是多变的,所以处理器的类型是object类型的
handle方法就是去执行处理器
getLastModified方法是Http协议相关的,这边就不多做介绍了
HandlerAdapter 接口的体系结构如下:
初始化过程
在DispatcherServlet.onRefresh()方法中初始化了HandlerAdapter组件
private void initHandlerAdapters(ApplicationContext context) { this.handlerAdapters = null; //默认情况下是this.detectAllHandlerAdapters=true, //检测容器中所有的HandlerAdapter的bean,并对其进行排序 if (this.detectAllHandlerAdapters=) { // Find all HandlerAdapters in the ApplicationContext, including ancestor contexts. Map<String, HandlerAdapter的bean,并对其进行排序> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false); if (!matchingBeans.isEmpty()) { this.handlerAdapters = new ArrayList<>(matchingBeans.values()); // We keep HandlerAdapters in sorted order. AnnotationAwareOrderComparator.sort(this.handlerAdapters); } } else { //this.detectAllHandlerAdapters=false的情况下,获取默认的名为handlerAdapter的bean try { HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class); this.handlerAdapters = Collections.singletonList(ha); } catch (NoSuchBeanDefinitionException ex) { // Ignore, we'll add a default HandlerAdapter later. } } //如果以上两种方式都没有获取到handlerAdapter的bean,则通过加载配置文件下的默认类 // 默认文件是DispatcherServlet.properties, //org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\ org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\ org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter,\ org.springframework.web.servlet.function.support.HandlerFunctionAdapter // Ensure we have at least some HandlerAdapters, by registering // default HandlerAdapters if no other adapters are found. if (this.handlerAdapters == null) { this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class); if (logger.isTraceEnabled()) { logger.trace("No HandlerAdapters declared for servlet '" + getServletName() + "': using default strategies from DispatcherServlet.properties"); } } }复制代码
handlerAdapter的初始化只要分为以下几步
首先判断是否需要检测关于HandlerAdapter的所有bean,true的情况下会去检测容器中的所有bean并对其进行排序,false的情况下会去获取名为handlerAdapter的bean
如果以上两种方式都没有获取的handlerAdapter的bean,则去加载配置文件DispatcherServlet.properties中的
org.springframework.web.servlet.HandlerAdapter属性中所有的类
HttpRequestHandlerAdapter
public class HttpRequestHandlerAdapter implements HandlerAdapter { //可以看出来supports的具体实现其实是很简单的,就是判断handler是否是HttpRequestHandler类型的 @Override public boolean supports(Object handler) { return (handler instanceof HttpRequestHandler); } //调用handleRequest方法执行的handler @Override @Nullable public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { ((HttpRequestHandler) handler).handleRequest(request, response); return null; } @Override public long getLastModified(HttpServletRequest request, Object handler) { if (handler instanceof LastModified) { return ((LastModified) handler).getLastModified(request); } return -1L; } }复制代码
SimpleContrllerHandlerAdapter
public class SimpleControllerHandlerAdapter implements HandlerAdapter { @Override public boolean supports(Object handler) { return (handler instanceof Controller); } @Override @Nullable public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return ((Controller) handler).handleRequest(request, response); } @Override public long getLastModified(HttpServletRequest request, Object handler) { if (handler instanceof LastModified) { return ((LastModified) handler).getLastModified(request); } return -1L; } }复制代码
SimpleControllerHandlerAdapter和HttpRequestHandlerAdapter的实现几乎是一样的,唯一的不同就是supports方法判断当前处理器是否是Controller类型的
AbstractHandlerMethodAdapter
AbstractHandlerMethodAdapter实现了HandlerAdapter和Ordered接口,继承了WebContentGenerator类
初始化
//最低优先级 private int order = Ordered.LOWEST_PRECEDENCE; //调用了WebContentGenerator的构造方法,当参数为false的时候,表示表示不需要严格效验HttpMethod public AbstractHandlerMethodAdapter() { // no restriction of HTTP methods by default super(false); }复制代码
supports方法
//判断handler是否是HandlerMethod类型,调用supportsInternal方法 @Override public final boolean supports方法,判断(Object handler) { return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler)); } /** * Given a handler method, return whether or not this adapter can support it. * @param handlerMethod the handler method to check * @return whether or not this adapter can adapt the given method */ //具体实现交于子类 protected abstract boolean supportsInternal(HandlerMethod handlerMethod);复制代码
实现supports方法,判断handler是否是HandlerMethod类型,调用supportsInternal方法,supportsInternal方法交于子类去实现,目前子类只有RequestMappingHandlerAdapter,其实现是直接返回true
handler方法
@Override @Nullable public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //调用handleInternal方法 return handleInternal(request, response, (HandlerMethod) handler); } /** * Use the given handler method to handle the request. * @param request current HTTP request * @param response current HTTP response * @param handlerMethod handler method to use. This object must have previously been passed to the * {@link #supportsInternal(HandlerMethod)} this interface, which must have returned {@code true}. * @return a ModelAndView object with the name of the view and the required model data, * or {@code null} if the request has been handled directly * @throws Exception in case of errors */ //交于其子类去实现 @Nullable protected abstract ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception;复制代码
handler 调用handleInternal方法,handleInternal方法交于其子类去实现
getLastModified方法
//调用的getLastModifiedInternal方法,getLastModifiedInternal方法交于其子类去实现 @Override public final long getLastModified(HttpServletRequest request, Object handler) { return getLastModifiedInternal(request, (HandlerMethod) handler); } /** * Same contract as for {@link javax.servlet.http.HttpServlet#getLastModified(HttpServletRequest)}. * @param request current HTTP request * @param handlerMethod handler method to use * @return the lastModified value for the given handler */ protected abstract long getLastModifiedInternal(HttpServletRequest request, HandlerMethod handlerMethod);复制代码
调用的getLastModifiedInternal方法,getLastModifiedInternal方法交于其子类去实现
AbstractHandlerMethodAdapter实现了HandlerAdapter中的三个方法,每一个方法都是调用自定义方法,而自定义的方法都是交于其子类去实现
RequestMappingHandlerAdapter
构造方法
@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()); } public AllEncompassingFormHttpMessageConverter() { try { addPartConverter(new SourceHttpMessageConverter<>()); } catch (Error err) { // Ignore when no TransformerFactory implementation is available } if (jaxb2Present && !jackson2XmlPresent) { addPartConverter(new Jaxb2RootElementHttpMessageConverter()); } if (jackson2Present) { addPartConverter(new MappingJackson2HttpMessageConverter()); } else if (gsonPresent) { addPartConverter(new GsonHttpMessageConverter()); } else if (jsonbPresent) { addPartConverter(new JsonbHttpMessageConverter()); } if (jackson2XmlPresent) { addPartConverter(new MappingJackson2XmlHttpMessageConverter()); } if (jackson2SmilePresent) { addPartConverter(new MappingJackson2SmileHttpMessageConverter()); } }复制代码
以上有许多属性,这边只介绍几个简单的属性
HandlerMethodArgumentResolverComposite argumentResolvers : 参数解析组合对象
HandlerMethodReturnValueHandlerComposite returnValueHandlers : 返回参数处理器组合对象
List<HttpMessageConverter<?>> messageConverters : HTTP消息转换器集合
List requestResponseBodyAdvice :requestResponseBodyAdvice 对象集合
从以上代码可以看出构造方法中初始化了多种消息转换器
afterPropertiesSet方法RequestMappingHandler实现了InitializingBean接口,所以在bean初始化后一定会执行afterPropertiesSet方法
@Override public void afterPropertiesSet() { // Do this first, it may add ResponseBody advice beans //初始化ControllerAdvice initControllerAdviceCache(); //初始化argumentResolvers参数解析对象 if (this.argumentResolvers == null) { List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers(); this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers); } 初始化initBinderArgumentResolver if (this.initBinderArgumentResolvers == null) { List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers(); this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers); } //初始化returnValueHandler if (this.returnValueHandlers == null) { List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers(); this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers); } }复制代码
initControllerAdviceCache
private void initControllerAdviceCache() { if (getApplicationContext() == null) { return; } //获取到所有带有@ControllerAdvice注解的的bean,并进行排序 List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext()); AnnotationAwareOrderComparator.sort(adviceBeans); List<Object> requestResponseBodyAdviceBeans = new ArrayList<>(); //遍历到获取到的bean for (ControllerAdviceBean adviceBean : adviceBeans) { Class<?> beanType = adviceBean.getBeanType(); if (beanType == null) { throw new IllegalStateException("Unresolvable type for ControllerAdviceBean: " + adviceBean); } //扫描带有'@ModelAttribute'注解却没有带有@RequestMapping注解的bean的方法,添加到modelAttributeAdviceCache属性中 //该方法用于处理执行方法前的Model Set<Method> attrMethods = MethodIntrospector.selectMethods(beanType, MODEL_ATTRIBUTE_METHODS); if (!attrMethods.isEmpty()) { this.modelAttributeAdviceCache.put(adviceBean, attrMethods); } //扫描带有'@InitBinder'注解的方法,添加到initBinderAdviceCache属性中 //该类方法用于方法执行前初始化数据绑定器 Set<Method> binderMethods = MethodIntrospector.selectMethods(beanType, INIT_BINDER_METHODS); if (!binderMethods.isEmpty()) { this.initBinderAdviceCache.put(adviceBean, binderMethods); } //如果是RequestBodyAdvice的子类则添加到requestResponseBodyAdviceBeans中 if (RequestBodyAdvice.class.isAssignableFrom(beanType)) { requestResponseBodyAdviceBeans.add(adviceBean); } //如果是ResponseBodyAdvice的子类则添加到requestResponseBodyAdviceBeans中 if (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"); } } }复制代码
supportsInternal方法supportsInternal方法中直接返回的true,这个就没有什么好说的了
@Override protected boolean supportsInternal(HandlerMethod handlerMethod) { return true; }复制代码
getLastModifiedInternal方法getLastModifiedInternal方法中直接返回的-1,这个也没有什么好说的
@Override protected long getLastModifiedInternal(HttpServletRequest request, HandlerMethod handlerMethod) { return -1; }复制代码
handleInternal
@Override protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ModelAndView mav; // <1> 校验请求(HttpMethod 和 Session 的校验) checkRequest(request); // Execute invokeHandlerMethod in synchronized block if required. // 同步相同 Session 的逻辑,默认情况false if (this.synchronizeOnSession) { HttpSession session = request.getSession(false); if (session != null) { // 获取Session的锁对象 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... mav = invokeHandlerMethod(request, response, handlerMethod); } if (!response.containsHeader(HEADER_CACHE_CONTROL)) { if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) { applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers); } else { prepareResponse(response); } } return mav; }
initControllerAdviceCache()方法中首先会去扫描带有@ControllerAdvice注解的bean,封装成一个ControllerAdviceBean类型的集合
遍历所有的ControllerAdviceBean对象,将带有'@ModelAttribute'注解却没有带有@RequestMapping注解的bean的方法,添加到modelAttributeAdviceCache属性中
遍历所有带有'@InitBinder'注解的方法,添加到initBinderAdviceCache属性中
判断ControllerAdviceBean是否是RequestBodyAdvice子类或者ResponseBodyAdvice子类,将其添加到requestResponseBodyAdviceBeans中,最后在将requestResponseBodyAdviceBeans中对象全部添加的requestResponseBodyAdvice中
调用initControllerAdviceCache()初始化ControllerAdvice相关
初始化argumentResolvers属性,调用getDefaultArgumentResolvers()获取到默认的参数解析对象数组
初始化initBinderArgumentResolvers属性,调用getDefaultInitBinderArgumentResolvers()获取到HandlerMethodArgumentResolver对象数组
初始化returnValueHandlers属性,调用getDefaultReturnValueHandlers获取到HandlerMethodReturnValueHandler(返回参数处理器集合)
getDefaultArgumentResolvers()和getDefaultInitBinderArgumentResolvers()以及getDefaultReturnValueHandlers()方法都没有什么好说的,都是初始化一些默认的对象,然后封装成集合返回
作者:从入门到入狱
链接:https://juejin.cn/post/7029596298768547847