當請求來到,並找到正確的Controller以及HandlerAdapter以後。就該執行方法了。web
這裏說的是 3.0版本以後的 RequestMappingAdapter 的解析執行過程。app
如下源碼都是簡化以後的。ide
首先,在DispatcherServlet部分源碼以下ui
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { // 找controller mappedHandler = getHandler(processedRequest); // 找HandlerAdaper HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // HandlerAdaper執行handle方法 mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); } }
最後的handle方法,是調用到了RequestMappingAdapter的handleInternal()方法。this
RequestMappingAdapter源碼以下spa
protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { mav = invokeHandlerMethod(request, response, handlerMethod); return mav; }
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { try { // 每一個請求過來的時候,都會新建一個ServletInvocableHandlerMethod 對象 ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod); // 給ServletInvocableHandlerMethod 對象設置方法參數解析器、方法返回值解析器 等 invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers); invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers); // 交給 ServletInvocableHandlerMethod 來處理請求了 invocableMethod.invokeAndHandle(webRequest, mavContainer); }
在 ServletInvocableHandlerMethod 類中,源碼以下debug
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { // 處理請求,invokeForRequest方法是父類InvocableHandlerMethod 的,父類主要處理請求 Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs); try { // 處理返回值 this.returnValueHandlers.handleReturnValue( returnValue, getReturnValueType(returnValue), mavContainer, webRequest); } }
InvocableHandlerMethod 類的源碼 以下對象
public Object invokeForRequest(NativeWebRequest request, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { // 獲取方法的參數 Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs); // 內部經過反射,調用controller 中的方法。 Object returnValue = doInvoke(args); return returnValue; }
private Object[] getMethodArgumentValues(NativeWebRequest request, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { MethodParameter[] parameters = getMethodParameters(); Object[] args = new Object[parameters.length]; for (int i = 0; i < parameters.length; i++) { MethodParameter parameter = parameters[i]; parameter.initParameterNameDiscovery(this.parameterNameDiscoverer); args[i] = resolveProvidedArgument(parameter, providedArgs); if (args[i] != null) { continue; } // 這個參數解析器是剛剛RequestMappingHandlerAdapter給注入的,是 HandlerMethodArgumentResolverComposite // 類型,它實現了HandlerMethodArgumentResolver接口,是個HandlerMethodArgumentResolver組合(集合) if (this.argumentResolvers.supportsParameter(parameter)) { try { // 解析參數,獲得參數。 args[i] = this.argumentResolvers.resolveArgument( parameter, mavContainer, request, this.dataBinderFactory); continue; } } return args; }
HandlerMethodArgumentResolverComposite類的 supportsParameter具體實現以下,其實就是在它的屬性裏有個List<HandlerMethodArgumentResolver>,而後看這個list裏面有沒有supports的。接口
@Override public boolean supportsParameter(MethodParameter parameter) { return (getArgumentResolver(parameter) != null); }
private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) { HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter); if (result == null) { for (HandlerMethodArgumentResolver methodArgumentResolver : this.argumentResolvers) { if (logger.isTraceEnabled()) { logger.trace("Testing if argument resolver [" + methodArgumentResolver + "] supports [" + parameter.getGenericParameterType() + "]"); } // 這個就是遍歷 List<HandlerMethodArgumentResolver> 裏面的參數解析器,看有沒有suppotrs的。 if (methodArgumentResolver.supportsParameter(parameter)) { result = methodArgumentResolver; this.argumentResolverCache.put(parameter, result); break; } } } return result; }
參數的解析大致流程就是上面的代碼了,補一下總體的結構。更加清晰一些get
RequestMappingHandlerAdapter的屬性有以下(部分)
// 如下是 處理方法參數的解析器,第一個是須要咱們自定義,第二個是默認的 private List<HandlerMethodArgumentResolver> customArgumentResolvers; private HandlerMethodArgumentResolverComposite argumentResolvers; // 如下是 處理方法返回值的解析器,第一個是須要咱們自定義,第二個是默認的 private List<HandlerMethodReturnValueHandler> customReturnValueHandlers; private HandlerMethodReturnValueHandlerComposite returnValueHandlers;
那麼RequestMappingHandlerAdapter的 argumentResolvers 和 returnValueHandlers是哪裏來的呢?
是Spring啓動時註冊RequestMappingHandlerAdapter的時候自動注入的。以下
private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() { List<HandlerMethodArgumentResolver> resolvers = new ArrayList<HandlerMethodArgumentResolver>(); // Annotation-based argument resolution 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 ServletModelAttributeMethodProcessor(false)); resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice)); resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters(), this.requestResponseBodyAdvice)); resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory())); resolvers.add(new RequestHeaderMapMethodArgumentResolver()); resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory())); resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory())); resolvers.add(new SessionAttributeMethodArgumentResolver()); resolvers.add(new RequestAttributeMethodArgumentResolver()); // Type-based argument resolution resolvers.add(new ServletRequestMethodArgumentResolver()); resolvers.add(new ServletResponseMethodArgumentResolver()); resolvers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice)); resolvers.add(new RedirectAttributesMethodArgumentResolver()); resolvers.add(new ModelMethodProcessor()); resolvers.add(new MapMethodProcessor()); resolvers.add(new ErrorsMethodArgumentResolver()); resolvers.add(new SessionStatusMethodArgumentResolver()); resolvers.add(new UriComponentsBuilderMethodArgumentResolver()); // Custom arguments if (getCustomArgumentResolvers() != null) { resolvers.addAll(getCustomArgumentResolvers()); } // Catch-all resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true)); resolvers.add(new ServletModelAttributeMethodProcessor(true)); return resolvers; }
而後執行handle方法的時候,RequestMappingHandlerAdapter 又把這兩個屬性給了
ServletInvocableHandlerMethod。而後ServletInvocableHandlerMethod利用解析器作各類處理。
ServletInvocableHandlerMethod 是主要處理 方法返回值的,它的父類是
InvocableHandlerMethod 是主要處理 方法參數的。 它的父類就是 HandlerMethod 了。
因此以上主要涉及的幾個類,名字都比較長。不能混淆,都要知道它們各自是幹嗎的,本文比較粗略,內部仍是沒有debug,我目前也就理解到這裏了。