/*
  * Don't consider parameter types that are available after conversion.
  * Message, Message<?> and Channel.
  */
 private boolean isEligibleParameter(MethodParameter methodParameter) {
   Type parameterType = methodParameter.getGenericParameterType();
   if (parameterType.equals(Channel.class)
       || parameterType.equals(org.springframework.amqp.core.Message.class)) {
     return false;
   }
   if (parameterType instanceof ParameterizedType) {
     ParameterizedType parameterizedType = (ParameterizedType) parameterType;
     if (parameterizedType.getRawType().equals(Message.class)) {
       return !(parameterizedType.getActualTypeArguments()[0] instanceof WildcardType);
     }
   }
   return !parameterType.equals(Message.class); // could be Message without a generic type
 }
 private MethodReturnValueHandler getReturnValueHandler(MethodParameter returnType) {
   for (MethodReturnValueHandler returnValueHandler : returnValueHandlers) {
     if (logger.isTraceEnabled()) {
       logger.trace(
           "Testing if return value handler ["
               + returnValueHandler
               + "] supports ["
               + returnType.getGenericParameterType()
               + "]");
     }
     if (returnValueHandler.supportsReturnType(returnType)) {
       return returnValueHandler;
     }
   }
   return null;
 }
  private Object tryParseAsJson(MethodParameter parameter, String str, Class<?> parameterType) {
    char c = str.charAt(0);
    boolean maybeJson = c == '{';
    if (maybeJson) return Json.unJson(str, parameterType);

    boolean maybeJsonArray = c == '[';
    if (maybeJsonArray) {
      Type genericParameterType = parameter.getGenericParameterType();
      boolean isGeneric = genericParameterType instanceof ParameterizedType;
      if (isGeneric) {
        ParameterizedType parameterizedType = (ParameterizedType) genericParameterType;
        Class<?> argType = (Class) parameterizedType.getActualTypeArguments()[0];

        return Json.unJsonArray(str, argType);
      }
    }
    return null;
  }
 private Class<?> getHttpEntityType(MethodParameter methodParam) {
   Assert.isAssignable(HttpEntity.class, methodParam.getParameterType());
   ParameterizedType type = (ParameterizedType) methodParam.getGenericParameterType();
   if (type.getActualTypeArguments().length == 1) {
     Type typeArgument = type.getActualTypeArguments()[0];
     if (typeArgument instanceof Class) {
       return (Class<?>) typeArgument;
     } else if (typeArgument instanceof GenericArrayType) {
       Type componentType = ((GenericArrayType) typeArgument).getGenericComponentType();
       if (componentType instanceof Class) {
         // Surely, there should be a nicer way to do this
         Object array = Array.newInstance((Class<?>) componentType, 0);
         return array.getClass();
       }
     }
   }
   throw new IllegalArgumentException(
       "HttpEntity parameter (" + methodParam.getParameterName() + ") is not parameterized");
 }
 /**
  * Find a registered {@link HandlerMethodReturnValueHandler} that supports the given return type.
  */
 private HandlerMethodReturnValueHandler getReturnValueHandler(MethodParameter returnType) {
   HandlerMethodReturnValueHandler result = this.returnValueHandlerCache.get(returnType);
   if (result == null) {
     for (HandlerMethodReturnValueHandler returnValueHandler : returnValueHandlers) {
       if (logger.isTraceEnabled()) {
         logger.trace(
             "Testing if return value handler ["
                 + returnValueHandler
                 + "] supports ["
                 + returnType.getGenericParameterType()
                 + "]");
       }
       if (returnValueHandler.supportsReturnType(returnType)) {
         result = returnValueHandler;
         this.returnValueHandlerCache.put(returnType, returnValueHandler);
         break;
       }
     }
   }
   return result;
 }
    private Type determineInferredType() {
      if (this.method == null) {
        return null;
      }

      Type genericParameterType = null;

      for (int i = 0; i < this.method.getParameterCount(); i++) {
        MethodParameter methodParameter = new MethodParameter(this.method, i);
        /*
         * We're looking for a single non-annotated parameter, or one annotated with @Payload.
         * We ignore parameters with type Message because they are not involved with conversion.
         */
        if (isEligibleParameter(methodParameter)
            && (methodParameter.getParameterAnnotations().length == 0
                || methodParameter.hasParameterAnnotation(Payload.class))) {
          if (genericParameterType == null) {
            genericParameterType = methodParameter.getGenericParameterType();
            if (genericParameterType instanceof ParameterizedType) {
              ParameterizedType parameterizedType = (ParameterizedType) genericParameterType;
              if (parameterizedType.getRawType().equals(Message.class)) {
                genericParameterType =
                    ((ParameterizedType) genericParameterType).getActualTypeArguments()[0];
              }
            }
          } else {
            if (MessagingMessageListenerAdapter.this.logger.isDebugEnabled()) {
              MessagingMessageListenerAdapter.this.logger.debug(
                  "Ambiguous parameters for target payload for method "
                      + this.method
                      + "; no inferred type header added");
            }
            return null;
          }
        }
      }

      return genericParameterType;
    }
 /**
  * {@inheritDoc}
  *
  * <p>Downcast {@link org.springframework.web.bind.WebDataBinder} to {@link
  * org.springframework.web.bind.ServletRequestDataBinder} before binding.
  *
  * @throws Exception
  * @see org.springframework.web.servlet.mvc.method.annotation.ServletRequestDataBinderFactory
  */
 protected void bindRequestParameters(
     ModelAndViewContainer mavContainer,
     WebDataBinderFactory binderFactory,
     WebDataBinder binder,
     NativeWebRequest request,
     MethodParameter parameter)
     throws Exception {
   Map<String, Boolean> hasProcessedPrefixMap = new HashMap<String, Boolean>();
   Class<?> targetType = binder.getTarget().getClass();
   ServletRequest servletRequest = prepareServletRequest(binder.getTarget(), request, parameter);
   WebDataBinder simpleBinder = binderFactory.createBinder(request, null, null);
   if (Collection.class.isAssignableFrom(targetType)) { // bind collection or array
     Type type = parameter.getGenericParameterType();
     Class<?> componentType = Object.class;
     Collection target = (Collection) binder.getTarget();
     List targetList = new ArrayList(target);
     if (type instanceof ParameterizedType) {
       componentType = (Class<?>) ((ParameterizedType) type).getActualTypeArguments()[0];
     }
     if (parameter.getParameterType().isArray()) {
       componentType = parameter.getParameterType().getComponentType();
     }
     for (Object key : servletRequest.getParameterMap().keySet()) {
       String prefixName = getPrefixName((String) key);
       // 每个prefix 只处理一次
       if (hasProcessedPrefixMap.containsKey(prefixName)) {
         continue;
       } else {
         hasProcessedPrefixMap.put(prefixName, Boolean.TRUE);
       }
       if (isSimpleComponent(prefixName)) { // bind simple type
         Map<String, Object> paramValues =
             WebUtils.getParametersStartingWith(servletRequest, prefixName);
         Matcher matcher = INDEX_PATTERN.matcher(prefixName);
         if (!matcher.matches()) { // 处理如 array=1&array=2的情况
           for (Object value : paramValues.values()) {
             targetList.add(simpleBinder.convertIfNecessary(value, componentType));
           }
         } else { // 处理如 array[0]=1&array[1]=2的情况
           int index = Integer.valueOf(matcher.group(1));
           if (targetList.size() <= index) {
             growCollectionIfNecessary(targetList, index);
           }
           targetList.set(
               index, simpleBinder.convertIfNecessary(paramValues.values(), componentType));
         }
       } else { // 处理如
         // votes[1].title=votes[1].title&votes[0].title=votes[0].title&votes[0].id=0&votes[1].id=1
         Object component = null;
         // 先查找老的 即已经在集合中的数据(而不是新添加一个)
         Matcher matcher = INDEX_PATTERN.matcher(prefixName);
         if (!matcher.matches()) {
           throw new IllegalArgumentException(
               "bind collection error, need integer index, key:" + key);
         }
         int index = Integer.valueOf(matcher.group(1));
         if (targetList.size() <= index) {
           growCollectionIfNecessary(targetList, index);
         }
         Iterator iterator = targetList.iterator();
         for (int i = 0; i < index; i++) {
           iterator.next();
         }
         component = iterator.next();
         if (component == null) {
           component = BeanUtils.instantiate(componentType);
         }
         WebDataBinder componentBinder = binderFactory.createBinder(request, component, null);
         component = componentBinder.getTarget();
         if (component != null) {
           ServletRequestParameterPropertyValues pvs =
               new ServletRequestParameterPropertyValues(servletRequest, prefixName, "");
           componentBinder.bind(pvs);
           validateIfApplicable(componentBinder, parameter);
           if (componentBinder.getBindingResult().hasErrors()) {
             if (isBindExceptionRequired(componentBinder, parameter)) {
               throw new BindException(componentBinder.getBindingResult());
             }
           }
           targetList.set(index, component);
         }
       }
       target.clear();
       target.addAll(targetList);
     }
   } else if (MapWapper.class.isAssignableFrom(targetType)) {
     Type type = parameter.getGenericParameterType();
     Class<?> keyType = Object.class;
     Class<?> valueType = Object.class;
     if (type instanceof ParameterizedType) {
       keyType = (Class<?>) ((ParameterizedType) type).getActualTypeArguments()[0];
       valueType = (Class<?>) ((ParameterizedType) type).getActualTypeArguments()[1];
     }
     MapWapper mapWapper = ((MapWapper) binder.getTarget());
     Map target = mapWapper.getInnerMap();
     if (target == null) {
       target = new HashMap();
       mapWapper.setInnerMap(target);
     }
     for (Object key : servletRequest.getParameterMap().keySet()) {
       String prefixName = getPrefixName((String) key);
       // 每个prefix 只处理一次
       if (hasProcessedPrefixMap.containsKey(prefixName)) {
         continue;
       } else {
         hasProcessedPrefixMap.put(prefixName, Boolean.TRUE);
       }
       Object keyValue = simpleBinder.convertIfNecessary(getMapKey(prefixName), keyType);
       if (isSimpleComponent(prefixName)) { // bind simple type
         Map<String, Object> paramValues =
             WebUtils.getParametersStartingWith(servletRequest, prefixName);
         for (Object value : paramValues.values()) {
           target.put(keyValue, simpleBinder.convertIfNecessary(value, valueType));
         }
       } else {
         Object component = target.get(keyValue);
         if (component == null) {
           component = BeanUtils.instantiate(valueType);
         }
         WebDataBinder componentBinder = binderFactory.createBinder(request, component, null);
         component = componentBinder.getTarget();
         if (component != null) {
           ServletRequestParameterPropertyValues pvs =
               new ServletRequestParameterPropertyValues(servletRequest, prefixName, "");
           componentBinder.bind(pvs);
           validateComponent(componentBinder, parameter);
           target.put(keyValue, component);
         }
       }
     }
   } else { // bind model
     ServletRequestDataBinder servletBinder = (ServletRequestDataBinder) binder;
     servletBinder.bind(servletRequest);
   }
 }
 public JAXBElement<?> resolveArgument(MessageContext messageContext, MethodParameter parameter)
     throws JAXBException {
   ParameterizedType parameterizedType = (ParameterizedType) parameter.getGenericParameterType();
   Class<?> clazz = (Class) parameterizedType.getActualTypeArguments()[0];
   return unmarshalElementFromRequestPayload(messageContext, clazz);
 }
 @Override
 protected boolean supportsRequestPayloadParameter(MethodParameter parameter) {
   Class<?> parameterType = parameter.getParameterType();
   Type genericType = parameter.getGenericParameterType();
   return JAXBElement.class.equals(parameterType) && genericType instanceof ParameterizedType;
 }
 /**
  * Generic type of parameter.
  *
  * @return generic type
  */
 public java.lang.reflect.Type getGenericParameterType() {
   return methodParameter.getGenericParameterType();
 }