handlerAdapter与方法调用(参数的解析)
Posted honger
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了handlerAdapter与方法调用(参数的解析)相关的知识,希望对你有一定的参考价值。
前提:当找到handler以后,那么就要让handler发挥作用,这个时候handlerAdapter就派上用场了 这里面比较复杂就是requestMappingHandlerAdapter了,其他的由于handler比较固定,基本上之前调用他们实现的接口的方法。 @Override public final boolean supports(Object handler) { return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler)); } supportsInternal方法子类实现,用于扩展,但在requestMappingHandlerAdapter子类中并没有做什么,直接返回true。 @Override public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return handleInternal(request, response, (HandlerMethod) handler); } handleInternal方法也有子类实现。在调用handler之前,会做一些数据绑定,比如会查找@ControllerAdvice注解,查找@InitBinder,@ModuleAttribute,查找实现了RequestBodyAdvice的类等等。 初始化一些参数解析器,校验器 RequestMappingHandlerAdapter实现了InitializingBean接口,所以在初始化这个adapter并且设置了相应的属性之后就会调用afterPropertiesSet方法 @Override public void afterPropertiesSet() { // Do this first, it may add ResponseBody advice beans //初始化@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; } if (logger.isInfoEnabled()) { logger.info("Looking for @ControllerAdvice: " + getApplicationContext()); } //在applicationContext容器中找到被@controllerAdvice标注的bean,并排序 List<ControllerAdviceBean> beans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext()); AnnotationAwareOrderComparator.sort(beans); //创建实现了@responseBodyAdvice的bean List<Object> requestResponseBodyAdviceBeans = new ArrayList<Object>(); for (ControllerAdviceBean bean : beans) { //查找被@ModelAttribute注解标注的方法 Set<Method> attrMethods = MethodIntrospector.selectMethods(bean.getBeanType(), MODEL_ATTRIBUTE_METHODS); if (!attrMethods.isEmpty()) { this.modelAttributeAdviceCache.put(bean, attrMethods); if (logger.isInfoEnabled()) { logger.info("Detected @ModelAttribute methods in " + bean); } } //查找被@InitBinder注解标注的方法 Set<Method> binderMethods = MethodIntrospector.selectMethods(bean.getBeanType(), INIT_BINDER_METHODS); if (!binderMethods.isEmpty()) { this.initBinderAdviceCache.put(bean, binderMethods); if (logger.isInfoEnabled()) { logger.info("Detected @InitBinder methods in " + bean); } } //查找父类是RequestBodyAdvice的bean if (RequestBodyAdvice.class.isAssignableFrom(bean.getBeanType())) { requestResponseBodyAdviceBeans.add(bean); if (logger.isInfoEnabled()) { logger.info("Detected RequestBodyAdvice bean in " + bean); } } //查找父类是ResponseBodyAdvice的bean if (ResponseBodyAdvice.class.isAssignableFrom(bean.getBeanType())) { requestResponseBodyAdviceBeans.add(bean); if (logger.isInfoEnabled()) { logger.info("Detected ResponseBodyAdvice bean in " + bean); } } } if (!requestResponseBodyAdviceBeans.isEmpty()) { //将使用@ControllerAdvice注解找的bean放到最前面 this.requestResponseBodyAdvice.addAll(0, requestResponseBodyAdviceBeans); } 方法返回后 接下来就开始初始化解析器了 if (this.argumentResolvers == null) { List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers(); this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers); } getDefaultArgumentResolvers方法 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())); // 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; } 准备就绪之后,开始调用handleInternal方法 @Override protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ModelAndView mav; //检查是否支持当前请求的方法,检查session是否为必须的 checkRequest(request); // Execute invokeHandlerMethod in synchronized block if required. //执行session同步 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... mav = invokeHandlerMethod(request, response, handlerMethod); } if (!response.containsHeader(HEADER_CACHE_CONTROL)) { if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) { applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers); } else { prepareResponse(response); } } return mav; } protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ServletWebRequest webRequest = new ServletWebRequest(request, response); //创建data绑定工厂,数据绑定是用来与String进行参数转换的 WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod); ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory); ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod); invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers); invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers); 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(); if (logger.isDebugEnabled()) { logger.debug("Found concurrent result value [" + result + "]"); } invocableMethod = invocableMethod.wrapConcurrentResult(result); } invocableMethod.invokeAndHandle(webRequest, mavContainer); if (asyncManager.isConcurrentHandlingStarted()) { return null; } return getModelAndView(mavContainer, modelFactory, webRequest); } private WebDataBinderFactory getDataBinderFactory(HandlerMethod handlerMethod) throws Exception { Class<?> handlerType = handlerMethod.getBeanType(); //从缓存中查找是否已经存在这个类型对应的@InitBinder方法 Set<Method> methods = this.initBinderCache.get(handlerType); if (methods == null) { //如果为空,就对当前handler进行遍历查找@InitBinder的方法 methods = MethodIntrospector.selectMethods(handlerType, INIT_BINDER_METHODS); //保存到缓存中 this.initBinderCache.put(handlerType, methods); } List<InvocableHandlerMethod> initBinderMethods = new ArrayList<InvocableHandlerMethod>(); // Global methods first遍历全局(也就是@ControllerAdvice标注的类的@InitBinder方法,这个在adapter的afterPropertiesSet方法中初始化的) for (Entry<ControllerAdviceBean, Set<Method>> entry : this.initBinderAdviceCache.entrySet()) { if (entry.getKey().isApplicableToBeanType(handlerType)) { Object bean = entry.getKey().resolveBean(); for (Method method : entry.getValue()) { //创建InvocableHandlerMethod对象并添加 initBinderMethods.add(createInitBinderMethod(bean, method)); } } } //添加完全局的之后,再添加当前处理器的 for (Method method : methods) { Object bean = handlerMethod.getBean(); initBinderMethods.add(createInitBinderMethod(bean, method)); } return createDataBinderFactory(initBinderMethods); } public boolean isApplicableToBeanType(Class<?> beanType) { //如果@controllerAdvice什么属性都没有写,说明将所有配置的方法应用到所有的handler中 if (!hasSelectors()) { return true; } else if (beanType != null) { for (String basePackage : this.basePackages) { if (beanType.getName().startsWith(basePackage)) { return true; } } for (Class<?> clazz : this.assignableTypes) { if (ClassUtils.isAssignable(clazz, beanType)) { return true; } } for (Class<? extends Annotation> annotationClass : this.annotations) { if (AnnotationUtils.findAnnotation(beanType, annotationClass) != null) { return true; } } } return false; } private InvocableHandlerMethod createInitBinderMethod(Object bean, Method method) { //InvocableHandlerMethod 是handlerMethod的子类 InvocableHandlerMethod binderMethod = new InvocableHandlerMethod(bean, method); binderMethod.setHandlerMethodArgumentResolvers(this.initBinderArgumentResolvers); binderMethod.setDataBinderFactory(new DefaultDataBinderFactory(this.webBindingInitializer)); binderMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer); return binderMethod; } 最后返回一个createDataBinderFactory(initBinderMethods); 回到invokeHandlerMethod方法,创建了DataBinderFactory后,接下来就是创建ModelFactory了 private ModelFactory getModelFactory(HandlerMethod handlerMethod, WebDataBinderFactory binderFactory) { //获取SessionAttributesHandler,这个处理器用来处理@SessionAttributes注解的方法 SessionAttributesHandler sessionAttrHandler = getSessionAttributesHandler(handlerMethod); Class<?> handlerType = handlerMethod.getBeanType(); //获取标注了@ModelAttribute的方法 Set<Method> methods = this.modelAttributeCache.get(handlerType); if (methods == null) { //如果缓存中没有就重新查找当前标注了@ModelAttribute的方法,并存到缓存中 methods = MethodIntrospector.selectMethods(handlerType, MODEL_ATTRIBUTE_METHODS); this.modelAttributeCache.put(handlerType, methods); } List<InvocableHandlerMethod> attrMethods = new ArrayList<InvocableHandlerMethod>(); // Global methods first添加全局的@ModelAttribute注解的方法 for (Entry<ControllerAdviceBean, Set<Method>> entry : this.modelAttributeAdviceCache.entrySet()) { if (entry.getKey().isApplicableToBeanType(handlerType)) { Object bean = entry.getKey().resolveBean(); for (Method method : entry.getValue()) { attrMethods.add(createModelAttributeMethod(binderFactory, bean, method)); } } } for (Method method : methods) { Object bean = handlerMethod.getBean(); attrMethods.add(createModelAttributeMethod(binderFactory, bean, method)); } //创建ModelFactory工厂 return new ModelFactory(attrMethods, binderFactory, sessionAttrHandler); } //第一个参数传入的是标记了@ModelAttribute的方法,第二个参数数据绑定,第三个是@SessionAttributes注解对应的处理器 public ModelFactory(List<InvocableHandlerMethod> handlerMethods, WebDataBinderFactory binderFactory, SessionAttributesHandler attributeHandler) { if (handlerMethods != null) { for (InvocableHandlerMethod handlerMethod : handlerMethods) { this.modelMethods.add(new ModelMethod(handlerMethod)); } } this.dataBinderFactory = binderFactory; this.sessionAttributesHandler = attributeHandler; } private ModelMethod(InvocableHandlerMethod handlerMethod) { this.handlerMethod = handlerMethod; for (MethodParameter parameter : handlerMethod.getMethodParameters()) { if (parameter.hasParameterAnnotation(ModelAttribute.class)) { this.dependencies.add(getNameForParameter(parameter)); } } } 当缓存什么的都弄好了之后就开始处理当前handleMethod了 ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod); invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers); invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers); invocableMethod.setDataBinderFactory(binderFactory); invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer); ModelAndViewContainer mavContainer = new ModelAndViewContainer(); //将FlashMap中的属性添加到mav容器中 mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request)); modelFactory.initModel(webRequest, mavContainer, invocableMethod); mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect); public void initModel(NativeWebRequest request, ModelAndViewContainer container, HandlerMethod handlerMethod) throws Exception { //从sessionAttribute中回复参数到mavContainer中 Map<String, ?> sessionAttributes = this.sessionAttributesHandler.retrieveAttributes(request); //合并参数,因为sessionAttribute中的参数可能会与flashmap中的参数冲突,但不会覆盖原来的参数 container.mergeAttributes(sessionAttributes); //调用modelAttribute注解的方法 invokeModelAttributeMethods(request, container); for (String name : findSessionAttributeArguments(handlerMethod)) { if (!container.containsAttribute(name)) { Object value = this.sessionAttributesHandler.retrieveAttribute(request, name); if (value == null) { throw new HttpSessionRequiredException("Expected session attribute ‘" + name + "‘"); } container.addAttribute(name, value); } } } invokeModelAttributeMethods(request, container); private void invokeModelAttributeMethods(NativeWebRequest request, ModelAndViewContainer container) throws Exception { while (!this.modelMethods.isEmpty()) { //获取第一个modelMethod方法,并将其移除,等下次调用的时候就就是第二个modelMethod,如果参数有@ModelAttribute,则优先处理 InvocableHandlerMethod modelMethod = getNextModelMethod(container).getHandlerMethod(); //获取模型值,即属性key值 String modelName = modelMethod.getMethodAnnotation(ModelAttribute.class).value(); //如果已经存在了就不再调用 if (container.containsAttribute(modelName)) { continue; } //调用方法 Object returnValue = modelMethod.invokeForRequest(request, container); if (!modelMethod.isVoid()){ String returnValueName = getNameForReturnValue(returnValue, modelMethod.getReturnType()); if (!container.containsAttribute(returnValueName)) { container.addAttribute(returnValueName, returnValue); } } } } private ModelMethod getNextModelMethod(ModelAndViewContainer container) { //遍历所有的modelmethod,如果他们的依赖存在,就优先使用这个方法参数与中有@ModelAttribute注解的modelmethod方法,否则就直接返回第一个modelmethod for (ModelMethod modelMethod : this.modelMethods) { if (modelMethod.checkDependencies(container)) { if (logger.isTraceEnabled()) { logger.trace("Selected @ModelAttribute method " + modelMethod); } this.modelMethods.remove(modelMethod); return modelMethod; } } //获取第一个modelmethod,并将它已移除 ModelMethod modelMethod = this.modelMethods.get(0); if (logger.isTraceEnabled()) { logger.trace("Selected @ModelAttribute method (not present: " + modelMethod.getUnresolvedDependencies(container)+ ") " + modelMethod); } this.modelMethods.remove(modelMethod); return modelMethod; } // public Object invokeForRequest(NativeWebRequest request, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { //获取方法参数值 Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs); if (logger.isTraceEnabled()) { StringBuilder sb = new StringBuilder("Invoking ["); sb.append(getBeanType().getSimpleName()).append("."); sb.append(getMethod().getName()).append("] method with arguments "); sb.append(Arrays.asList(args)); logger.trace(sb.toString()); } Object returnValue = doInvoke(args); if (logger.isTraceEnabled()) { logger.trace("Method [" + getMethod().getName() + "] returned [" + returnValue + "]"); } 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); //给当前参数封装对象设置参数类型 GenericTypeResolver.resolveParameterType(parameter, getBean().getClass()); //尝试从给定的providedArgs参数查找对应类型的参数,如果找到就设置这个值到args数组中,这个providedArgs在这里是没有传递任何值的 args[i] = resolveProvidedArgument(parameter, providedArgs); //如果不为空就continue,表示已经有值了 if (args[i] != null) { continue; } //查找有没有支持此参数解析的解析器 if (this.argumentResolvers.supportsParameter(parameter)) { try { //解析参数 args[i] = this.argumentResolvers.resolveArgument( parameter, mavContainer, request, this.dataBinderFactory); continue; } catch (Exception ex) { if (logger.isDebugEnabled()) { logger.debug(getArgumentResolutionErrorMessage("Error resolving argument", i), ex); } throw ex; } } if (args[i] == null) { String msg = getArgumentResolutionErrorMessage("No suitable resolver for argument", i); throw new IllegalStateException(msg); } } return args; } (this.argumentResolvers.supportsParameter(parameter) private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) { //先从缓存中找,如果没有找到,在遍历所有的解析器,这个解析器集合保存在一个解析器Composite类中,SpringMVC中这样的类一般是使用的责任链模式 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() + "]"); } if (methodArgumentResolver.supportsParameter(parameter)) { result = methodArgumentResolver; this.argumentResolverCache.put(parameter, result); break; } } } return result; } this.argumentResolvers.resolveArgument( parameter, mavContainer, request, this.dataBinderFactory);方法体如下 @Override public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { //获取参数解析器,如果没有获取到就抛出错误 HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter); if (resolver == null) { throw new IllegalArgumentException("Unknown parameter type [" + parameter.getParameterType().getName() + "]"); } return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory); } HandlerMethodArgumentResolver的实现类有很多,这里选几个分析一下 首先先分析一下RequestResponseBodyMethodProcessor,这是一个集argumentResolve和handlerReturnValue于一身的类 直接看解析方法resolveArgument: @Override public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { //使用转化器进行参数的转换 Object arg = readWithMessageConverters(webRequest, parameter, parameter.getGenericParameterType()); String name = Conventions.getVariableNameForParameter(parameter); WebDataBinder binder = binderFactory.createBinder(webRequest, arg, name); if (arg != null) { validateIfApplicable(binder, parameter); if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) { throw new MethodArgumentNotValidException(parameter, binder.getBindingResult()); } } mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult()); return arg; } protected <T> Object readWithMessageConverters(NativeWebRequest webRequest, MethodParameter methodParam, Type paramType) throws IOException, HttpMediaTypeNotSupportedException, HttpMessageNotReadableException { HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class); ServletServerHttpRequest inputMessage = new ServletServerHttpRequest(servletRequest); Object arg = readWithMessageConverters(inputMessage, methodParam, paramType); if (arg == null) { if (methodParam.getParameterAnnotation(RequestBody.class).required()) { throw new HttpMessageNotReadableException("Required request body is missing: " + methodParam.getMethod().toGenericString()); } } return arg; } readWithMessageConverters方法 protected <T> Object readWithMessageConverters(HttpInputMessage inputMessage, MethodParameter param, Type targetType) throws IOException, HttpMediaTypeNotSupportedException, HttpMessageNotReadableException { MediaType contentType; boolean noContentType = false; try { //获取请求的ContentType contentType = inputMessage.getHeaders().getContentType(); } catch (InvalidMediaTypeException ex) { throw new HttpMediaTypeNotSupportedException(ex.getMessage()); } if (contentType == null) { noContentType = true; //设置默认的contentType contentType = MediaType.APPLICATION_OCTET_STREAM; } //获取类的类型 Class<?> contextClass = (param != null ? param.getContainingClass() : null); //获取的参数的泛型类型 Class<T> targetClass = (targetType instanceof Class<?> ? (Class<T>) targetType : null); //如果没有就再次尝试设置一遍 if (targetClass == null) { ResolvableType resolvableType = (param != null ? ResolvableType.forMethodParameter(param) : ResolvableType.forType(targetType)); targetClass = (Class<T>) resolvableType.resolve(); } //获取请求方法 HttpMethod httpMethod = ((HttpRequest) inputMessage).getMethod(); Object body = NO_VALUE; try { inputMessage = new EmptyBodyCheckingHttpInputMessage(inputMessage); //遍历这个解析器中的所有的converter,判断是否是泛化的转换器 for (HttpMessageConverter<?> converter : this.messageConverters) { Class<HttpMessageConverter<?>> converterType = (Class<HttpMessageConverter<?>>) converter.getClass(); if (converter instanceof GenericHttpMessageConverter) { GenericHttpMessageConverter<?> genericConverter = (GenericHttpMessageConverter<?>) converter; //判断是否能够进行解析 if (genericConverter.canRead(targetType, contextClass, contentType)) { if (logger.isDebugEnabled()) { logger.debug("Read [" + targetType + "] as "" + contentType + "" with [" + converter + "]"); } if (inputMessage.getBody() != null) { //如果请求体有值,那么就尝试调用实现了RequestAdvice的类,对请求体进行预先处理 inputMessage = getAdvice().beforeBodyRead(inputMessage, param, targetType, converterType); //使用converter进行转化 body = genericConverter.read(targetType, contextClass, inputMessage); //对处理完的body进行后置处理,就是使用实现了ResponseAdvice的类进行处理 body = getAdvice().afterBodyRead(body, inputMessage, param, targetType, converterType); } else { body = null; //处理空请求体 body = getAdvice().handleEmptyBody(body, inputMessage, param, targetType, converterType); } break; } } //如果不是泛化的转换器,那么就判断目标class是否为空。 else if (targetClass != null) { if (converter.canRead(targetClass, contentType)) { if (logger.isDebugEnabled()) { logger.debug("Read [" + targetType + "] as "" + contentType + "" with [" + converter + "]"); } if (inputMessage.getBody() != null) { inputMessage = getAdvice().beforeBodyRead(inputMessage, param, targetType, converterType); body = ((HttpMessageConverter<T>) converter).read(targetClass, inputMessage); body = getAdvice().afterBodyRead(body, inputMessage, param, targetType, converterType); } else { body = null; body = getAdvice().handleEmptyBody(body, inputMessage, param, targetType, converterType); } break; } } } } catch (IOException ex) { throw new HttpMessageNotReadableException("Could not read document: " + ex.getMessage(), ex); } //如果body没有被处理过 if (body == NO_VALUE) { if (httpMethod == null || !SUPPORTED_METHODS.contains(httpMethod) || (noContentType && inputMessage.getBody() == null)) { return null; } throw new HttpMediaTypeNotSupportedException(contentType, this.allSupportedMediaTypes); } canRead,判断是否可以处理这个请求类型的数据,对于json来说text/html肯定是不能进行处理的 protected boolean canRead(MediaType mediaType) { if (mediaType == null) { return true; } for (MediaType supportedMediaType : getSupportedMediaTypes()) { if (supportedMediaType.includes(mediaType)) { return true; } } return false; } 解析好后继续 public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { Object arg = readWithMessageConverters(webRequest, parameter, parameter.getGenericParameterType()); //如果指定的参数名为URL,连续两个大写字母的那么就保持它原来的样子,其他的就把第一个字母变成小写,如果是集合类的那么将泛型类型加上list字符串 String name = Conventions.getVariableNameForParameter(parameter); //创建数据绑定器 WebDataBinder binder = binderFactory.createBinder(webRequest, arg, name); if (arg != null) { //对参数进行校验 validateIfApplicable(binder, parameter); //查看是否发生了异常 if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) { //抛出参数校验不通过的异常 throw new MethodArgumentNotValidException(parameter, binder.getBindingResult()); } } //保存绑定数据后的结果信息 mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult()); return arg; } public static String getVariableNameForParameter(MethodParameter parameter) { Assert.notNull(parameter, "MethodParameter must not be null"); Class<?> valueClass; boolean pluralize = false; if (parameter.getParameterType().isArray()) { //获取数组的元素类型 valueClass = parameter.getParameterType().getComponentType(); pluralize = true; } else if (Collection.class.isAssignableFrom(parameter.getParameterType())) { //获取集合的泛型参数类型 valueClass = GenericCollectionTypeResolver.getCollectionParameterType(parameter); if (valueClass == null) { throw new IllegalArgumentException( "Cannot generate variable name for non-typed Collection parameter type"); } //设置为TRUE pluralize = true; } else { valueClass = parameter.getParameterType(); } //获取名字,出去包名 String name = ClassUtils.getShortNameAsProperty(valueClass); //如果pluralize为true,那么就在名字候命加上list字符串 return (pluralize ? pluralize(name) : name); } @Override public final WebDataBinder createBinder(NativeWebRequest webRequest, Object target, String objectName) throws Exception { //创建webdata 绑定 WebDataBinder dataBinder = createBinderInstance(target, objectName, webRequest); if (this.initializer != null) { this.initializer.initBinder(dataBinder, webRequest); } //开始调用绑定方法 initBinder(dataBinder, webRequest); return dataBinder; } initBinder方法 public void initBinder(WebDataBinder binder, NativeWebRequest request) throws Exception { for (InvocableHandlerMethod binderMethod : this.binderMethods) { if (isBinderMethodApplicable(binderMethod, binder)) { //跟前面调用方法是一样的,不过这次传入了一个提供的参数,那就是webDataBinder的实例,所以我们可以在@initBinder方法中添加一些校验器,编辑器等等操作。 Object returnValue = binderMethod.invokeForRequest(request, null, binder); if (returnValue != null) { throw new IllegalStateException("@InitBinder methods should return void: " + binderMethod); } } } } 创建了webDataBinder之后,并且如果我们在@initBinder注解的方法中做了一些事情,比如添加了校验器啥的,接下来的代码如下 if (arg != null) { validateIfApplicable(binder, parameter); if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) { throw new MethodArgumentNotValidException(parameter, binder.getBindingResult()); } } mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult()); //校验 protected void validateIfApplicable(WebDataBinder binder, MethodParameter methodParam) { Annotation[] annotations = methodParam.getParameterAnnotations(); for (Annotation ann : annotations) { //只有注释了@valid的参数才会进行校验 Validated validatedAnn = AnnotationUtils.getAnnotation(ann, Validated.class); if (validatedAnn != null || ann.annotationType().getSimpleName().startsWith("Valid")) { //获取注解中value值,这些值可以最为校验分组用,SpringMVC的校验使用的JSR303校验和自定义校验器 Object hints = (validatedAnn != null ? validatedAnn.value() : AnnotationUtils.getValue(ann)); Object[] validationHints = (hints instanceof Object[] ? (Object[]) hints : new Object[] {hints}); //开始校验 binder.validate(validationHints); break; } } } //遍历校验器进行校验 public void validate(Object... validationHints) { for (Validator validator : getValidators()) { //使用JSR303的方式校验 if (!ObjectUtils.isEmpty(validationHints) && validator instanceof SmartValidator) { ((SmartValidator) validator).validate(getTarget(), getBindingResult(), validationHints); } else if (validator != null) { //使用自定义校验器校验 validator.validate(getTarget(), getBindingResult()); } } } 好了,对于RequestBody注解的参数就是这么解析的。 来研究一下ModelAttributeMethodProcessor是怎么解析的 @Override public boolean supportsParameter(MethodParameter parameter) { //判断参数是否有@ModelAttribute注解 if (parameter.hasParameterAnnotation(ModelAttribute.class)) { return true; } else if (this.annotationNotRequired) { return !BeanUtils.isSimpleProperty(parameter.getParameterType()); } else { return false; } } //解析参数 public final Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { //获取参数名,先从注解的指定的名称找,如果没有就用Conventions.getVariableNameForParameter(parameter)方法获取参数名,这个在前面就已经使用过了 String name = ModelFactory.getNameForParameter(parameter); //判断这个参数是否在MavContainer中已经存在了,如果存在就直接获取这个参数值,如果没有找到就去request中寻找参数 Object attribute = (mavContainer.containsAttribute(name) ? mavContainer.getModel().get(name) : createAttribute(name, parameter, binderFactory, webRequest)); //创建WebDataBinder ,调用@initBinder注解的绑定方法 WebDataBinder binder = binderFactory.createBinder(webRequest, attribute, name); if (binder.getTarget() != null) { //这里是绑定请求的参数 bindRequestParameters(binder, webRequest); validateIfApplicable(binder, parameter); if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) { throw new BindException(binder.getBindingResult()); } } // Add resolved attribute and BindingResult at the end of the model Map<String, Object> bindingResultModel = binder.getBindingResult().getModel(); mavContainer.removeAttributes(bindingResultModel); mavContainer.addAllAttributes(bindingResultModel); return binder.convertIfNecessary(binder.getTarget(), parameter.getParameterType(), parameter); } protected void bindRequestParameters(WebDataBinder binder, NativeWebRequest request) { ServletRequest servletRequest = request.getNativeRequest(ServletRequest.class); ServletRequestDataBinder servletBinder = (ServletRequestDataBinder) binder; servletBinder.bind(servletRequest); } public void bind(ServletRequest request) { //解析创建成一个MutablePropertyValues MutablePropertyValues mpvs = new ServletRequestParameterPropertyValues(request); //判断是否为MultipartRequest 类型,如果是就获取这种类型的请求 MultipartRequest multipartRequest = WebUtils.getNativeRequest(request, MultipartRequest.class); if (multipartRequest != null) { bindMultipart(multipartRequest.getMultiFileMap(), mpvs); } //获取url中的变量Map用url定义的参数值,如果已经在mpvs存在的参数将不会覆盖 addBindValues(mpvs, request); //绑定参数 doBind(mpvs); } //创建MutablePropertyValues时的解析,解析成一个去掉指定前缀的Map,当然这里没有设置前缀 public static Map<String, Object> getParametersStartingWith(ServletRequest request, String prefix) { Assert.notNull(request, "Request must not be null"); Enumeration<String> paramNames = request.getParameterNames(); Map<String, Object> params = new TreeMap<String, Object>(); if (prefix == null) { prefix = ""; } while (paramNames != null && paramNames.hasMoreElements()) { String paramName = paramNames.nextElement(); if ("".equals(prefix) || paramName.startsWith(prefix)) { String unprefixed = paramName.substring(prefix.length()); String[] values = request.getParameterValues(paramName); if (values == null || values.length == 0) { // Do nothing, no values found at all. } else if (values.length > 1) { params.put(unprefixed, values); } else { params.put(unprefixed, values[0]); } } } return params; } 然后在传入这个paramMap到构造器 public MutablePropertyValues(Map<?, ?> original) { // We can optimize this because it‘s all new: // There is no replacement of existing property values. if (original != null) { this.propertyValueList = new ArrayList<PropertyValue>(original.size()); for (Map.Entry<?, ?> entry : original.entrySet()) { //propertyValueList是一个list,存储着PropertyValue对象,这个对象存着请求参数的名称和对应的值。 this.propertyValueList.add(new PropertyValue(entry.getKey().toString(), entry.getValue())); } } else { this.propertyValueList = new ArrayList<PropertyValue>(0); } } protected void bindMultipart(Map<String, List<MultipartFile>> multipartFiles, MutablePropertyValues mpvs) { for (Map.Entry<String, List<MultipartFile>> entry : multipartFiles.entrySet()) { String key = entry.getKey(); List<MultipartFile> values = entry.getValue(); if (values.size() == 1) { MultipartFile value = values.get(0); //默认情况下会保存空的MultipartFiles,所以即使你的上传文件框没有上传文件,也会存在空的文件 if (isBindEmptyMultipartFiles() || !value.isEmpty()) { mpvs.add(key, value); } } else { mpvs.add(key, values); } } } 开始绑定参数 @Override protected void doBind(MutablePropertyValues mpvs) { //检查有default值前缀的参数 checkFieldDefaults(mpvs); //检查有标记前缀的参数 checkFieldMarkers(mpvs); 真正绑定参数的方法 super.doBind(mpvs); } checkFieldDefaults方法: protected void checkFieldDefaults(MutablePropertyValues mpvs) { //如果字段默认的前缀不为空,那么就去掉前缀,然后判断这个属性在对应的参数对象中是否可写,并且在mpvs中不存在这个属性参会加入到mvps中,并且移除之前的 if (getFieldDefaultPrefix() != null) { String fieldDefaultPrefix = getFieldDefaultPrefix(); PropertyValue[] pvArray = mpvs.getPropertyValues(); for (PropertyValue pv : pvArray) { if (pv.getName().startsWith(fieldDefaultPrefix)) { String field = pv.getName().substring(fieldDefaultPrefix.length()); if (getPropertyAccessor().isWritableProperty(field) && !mpvs.contains(field)) { mpvs.add(field, pv.getValue()); } mpvs.removePropertyValue(pv); } } } } 这个方法和上面的是一样的道理 protected void checkFieldMarkers(MutablePropertyValues mpvs) { if (getFieldMarkerPrefix() != null) { String fieldMarkerPrefix = getFieldMarkerPrefix(); PropertyValue[] pvArray = mpvs.getPropertyValues(); for (PropertyValue pv : pvArray) { if (pv.getName().startsWith(fieldMarkerPrefix)) { String field = pv.getName().substring(fieldMarkerPrefix.length()); if (getPropertyAccessor().isWritableProperty(field) && !mpvs.contains(field)) { Class<?> fieldType = getPropertyAccessor().getPropertyType(field); mpvs.add(field, getEmptyValue(field, fieldType)); } mpvs.removePropertyValue(pv); } } } } 接下来调用了 protected void doBind(MutablePropertyValues mpvs) { //检查是否是运行的字段,这些字段都可以在@initBinder注解的方法中指定 checkAllowedFields(mpvs); //判断是否为必须的字段 checkRequiredFields(mpvs); //应用属性值 applyPropertyValues(mpvs); } //应用指定的值到对应的对象中 protected void applyPropertyValues(MutablePropertyValues mpvs) { try { // Bind request parameters onto target object. //绑定请求参数到目标参数中 getPropertyAccessor().setPropertyValues(mpvs, isIgnoreUnknownFields(), isIgnoreInvalidFields()); } catch (PropertyBatchUpdateException ex) { // Use bind error processor to create FieldErrors. for (PropertyAccessException pae : ex.getPropertyAccessExceptions()) { getBindingErrorProcessor().processPropertyAccessException(pae, getInternalBindingResult()); } } } 接下来就是对参数进行类型转换 return binder.convertIfNecessary(binder.getTarget(), parameter.getParameterType(), parameter); public <T> T convertIfNecessary(String propertyName, Object oldValue, Object newValue, Class<T> requiredType, TypeDescriptor typeDescriptor) throws IllegalArgumentException { // Custom editor for this type?获取@initBinder注解的方法中自定义的参数编辑器 PropertyEditor editor = this.propertyEditorRegistry.findCustomEditor(requiredType, propertyName); ConversionFailedException conversionAttemptEx = null; // No custom editor but custom ConversionService specified? ConversionService conversionService = this.propertyEditorRegistry.getConversionService(); if (editor == null && conversionService != null && newValue != null && typeDescriptor != null) { TypeDescriptor sourceTypeDesc = TypeDescriptor.forObject(newValue); if (conversionService.canConvert(sourceTypeDesc, typeDescriptor)) { try { //如果可以转换就进行转换 return (T) conversionService.convert(newValue, sourceTypeDesc, typeDescriptor); } catch (ConversionFailedException ex) { // fallback to default conversion logic below conversionAttemptEx = ex; } } } Object convertedValue = newValue; 。。。。。。。。。。。。。。。。。。。。。。。(代码较长,省略) 当所有的参数都解析完毕后,调用方法 Object returnValue = doInvoke(args); //如果不出例外,就直接使用放射方法调用 protected Object doInvoke(Object... args) throws Exception { ReflectionUtils.makeAccessible(getBridgedMethod()); try { return getBridgedMethod().invoke(getBean(), args); } catch (IllegalArgumentException ex) { assertTargetBean(getBridgedMethod(), getBean(), args); String message = (ex.getMessage() != null ? ex.getMessage() : "Illegal argument"); throw new IllegalStateException(getInvocationErrorMessage(message, args), ex); } catch (InvocationTargetException ex) { // Unwrap for HandlerExceptionResolvers ... Throwable targetException = ex.getTargetException(); if (targetException instanceof RuntimeException) { throw (RuntimeException) targetException; } else if (targetException instanceof Error) { throw (Error) targetException; } else if (targetException instanceof Exception) { throw (Exception) targetException; } else { String msg = getInvocationErrorMessage("Failed to invoke controller method", args); throw new IllegalStateException(msg, targetException); } } }
以上是关于handlerAdapter与方法调用(参数的解析)的主要内容,如果未能解决你的问题,请参考以下文章
SpringMVC源码解析- HandlerAdapter - ModelFactory
Spring 源码解析之HandlerAdapter源码解析
Spring 源码解析之HandlerAdapter源码解析