示例#1
0
 public Map<?, ?> resolve(Invocation inv, ParamMetaData metaData) {
   if (StringUtils.isNotEmpty(metaData.getParamName())) {
     Class<?>[] genericTypes = (Class[]) metaData.getUserObject(this);
     Class<?> keyType = genericTypes[0];
     Class<?> valueType = genericTypes[1];
     Map<?, ?> toConvert =
         WebUtils.getParametersStartingWith(
             inv.getRequest(), metaData.getParamName() + MAP_SEPARATOR);
     if (toConvert != null) {
       if (keyType != String.class || valueType != String.class) {
         Map<Object, Object> ret = new HashMap<Object, Object>();
         for (Map.Entry<?, ?> entry : toConvert.entrySet()) {
           Object key = entry.getKey();
           Object value = entry.getValue();
           TypeConverter typeConverter = SafedTypeConverterFactory.getCurrentConverter();
           if (keyType != String.class) {
             key = typeConverter.convertIfNecessary(key, keyType);
           }
           if (valueType != String.class) {
             value = typeConverter.convertIfNecessary(value, valueType);
           }
           ret.put(key, value);
         }
         return ret;
       }
       return toConvert;
     }
   }
   return new HashMap<Object, Object>(2);
 }
示例#2
0
 @SuppressWarnings("unchecked")
 private static Object resolveArray(
     Invocation inv, ParamMetaData metaData, Class<?> compnentType) {
   if (compnentType == MultipartFile.class) {
     String filterName = metaData.getParamName();
     if (filterName == null) {
       filterName = "";
     }
     if (inv.getRequest() instanceof MultipartRequest) {
       List<MultipartFile> files = new LinkedList<MultipartFile>();
       MultipartRequest multipartRequest = (MultipartRequest) inv.getRequest();
       Iterator<String> names = multipartRequest.getFileNames();
       while (names.hasNext()) {
         String name = names.next();
         if (name.startsWith(filterName)) {
           files.add(multipartRequest.getFile(name));
         }
       }
       return files.toArray(new MultipartFile[0]);
     } else {
       if (logger.isDebugEnabled()) {
         logger.debug(
             "cann't "
                 + "set MultipartFile param to method "
                 + ", the request is not a MultipartRequest");
       }
     }
   } else {
     Object toConvert = null;
     for (String paramName : metaData.getParamNames()) {
       if (paramName != null) {
         toConvert = inv.getRequest().getParameterValues(paramName);
         if (toConvert != null) {
           break;
         }
       }
     }
     if (toConvert != null) {
       if (((String[]) toConvert).length == 1) {
         toConvert = ((String[]) toConvert)[0].split(",");
       }
       Class<?> arrayType;
       if (metaData.getParamType().isArray()) {
         arrayType = metaData.getParamType();
       } else {
         arrayType = arrayTypeMap.get(compnentType);
         if (arrayType == null) {
           arrayType = Array.newInstance((Class<?>) compnentType, 0).getClass();
         }
       }
       TypeConverter typeConverter = SafedTypeConverterFactory.getCurrentConverter();
       Object array = typeConverter.convertIfNecessary(toConvert, arrayType);
       return array;
     }
   }
   return Array.newInstance((Class<?>) compnentType, 0);
 }
  /** Resolve the prepared arguments stored in the given bean definition. */
  private Object[] resolvePreparedArguments(
      String beanName,
      RootBeanDefinition mbd,
      BeanWrapper bw,
      Member methodOrCtor,
      Object[] argsToResolve) {

    Class<?>[] paramTypes =
        (methodOrCtor instanceof Method
            ? ((Method) methodOrCtor).getParameterTypes()
            : ((Constructor<?>) methodOrCtor).getParameterTypes());
    TypeConverter converter =
        (this.beanFactory.getCustomTypeConverter() != null
            ? this.beanFactory.getCustomTypeConverter()
            : bw);
    BeanDefinitionValueResolver valueResolver =
        new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter);
    Object[] resolvedArgs = new Object[argsToResolve.length];
    for (int argIndex = 0; argIndex < argsToResolve.length; argIndex++) {
      Object argValue = argsToResolve[argIndex];
      MethodParameter methodParam = MethodParameter.forMethodOrConstructor(methodOrCtor, argIndex);
      GenericTypeResolver.resolveParameterType(methodParam, methodOrCtor.getDeclaringClass());
      if (argValue instanceof AutowiredArgumentMarker) {
        argValue = resolveAutowiredArgument(methodParam, beanName, null, converter);
      } else if (argValue instanceof BeanMetadataElement) {
        argValue = valueResolver.resolveValueIfNecessary("constructor argument", argValue);
      } else if (argValue instanceof String) {
        argValue = this.beanFactory.evaluateBeanDefinitionString((String) argValue, mbd);
      }
      Class<?> paramType = paramTypes[argIndex];
      try {
        resolvedArgs[argIndex] = converter.convertIfNecessary(argValue, paramType, methodParam);
      } catch (TypeMismatchException ex) {
        String methodType =
            (methodOrCtor instanceof Constructor ? "constructor" : "factory method");
        throw new UnsatisfiedDependencyException(
            mbd.getResourceDescription(),
            beanName,
            argIndex,
            paramType,
            "Could not convert "
                + methodType
                + " argument value of type ["
                + ObjectUtils.nullSafeClassName(argValue)
                + "] to required type ["
                + paramType.getName()
                + "]: "
                + ex.getMessage());
      }
    }
    return resolvedArgs;
  }
  public Object[] resolve(final Invocation inv, final ParameterBindingResult parameterBindingResult)
      throws Exception {
    Object[] parameters = new Object[paramMetaDatas.length];
    for (int i = 0; i < resolvers.length; i++) {
      if (resolvers[i] == null) {
        continue;
      }
      try {
        if (logger.isDebugEnabled()) {
          logger.debug(
              "Resolves parameter "
                  + paramMetaDatas[i].getParamType().getSimpleName()
                  + " using "
                  + resolvers[i].getClass().getName());
        }
        parameters[i] = resolvers[i].resolve(inv, paramMetaDatas[i]);
        // afterPropertiesSet
        if (parameters[i] instanceof InitializingBean) {
          ((InitializingBean) parameters[i]).afterPropertiesSet();
        }
        if (parameters[i] == null) {
          DefValue defValudeAnnotation = paramMetaDatas[i].getAnnotation(DefValue.class);
          if (defValudeAnnotation != null && paramMetaDatas[i].getParamType() == String.class) {
            parameters[i] = defValudeAnnotation.value();
          }
        }
      } catch (TypeMismatchException e) {
        // 出现这个错误肯定是解析一般参数失败导致的,而非bean里面的某个属性值的解析失败

        logger.debug("", e);

        // 对简单类型的参数,设置一个默认值给它以支持对该方法的继续调用
        if (paramMetaDatas[i].getParamType().isPrimitive()) {
          DefValue defValudeAnnotation = paramMetaDatas[i].getAnnotation(DefValue.class);
          if (defValudeAnnotation == null
              || DefValue.NATIVE_DEFAULT.equals(defValudeAnnotation.value())) {
            // 对这最常用的类型做一下if-else判断,其他类型就简单使用converter来做吧
            if (paramMetaDatas[i].getParamType() == int.class) {
              parameters[i] = Integer.valueOf(0);
            } else if (paramMetaDatas[i].getParamType() == long.class) {
              parameters[i] = Long.valueOf(0);
            } else if (paramMetaDatas[i].getParamType() == boolean.class) {
              parameters[i] = Boolean.FALSE;
            } else if (paramMetaDatas[i].getParamType() == double.class) {
              parameters[i] = Double.valueOf(0);
            } else if (paramMetaDatas[i].getParamType() == float.class) {
              parameters[i] = Float.valueOf(0);
            } else {
              TypeConverter typeConverter = SafedTypeConverterFactory.getCurrentConverter();
              parameters[i] =
                  typeConverter.convertIfNecessary("0", paramMetaDatas[i].getParamType());
            }
          } else {
            TypeConverter typeConverter = SafedTypeConverterFactory.getCurrentConverter();
            parameters[i] =
                typeConverter.convertIfNecessary(
                    defValudeAnnotation.value(), paramMetaDatas[i].getParamType());
          }
        }
        //
        String paramName = parameterNames[i];
        if (paramName == null) {
          for (String name : paramMetaDatas[i].getParamNames()) {
            if ((paramName = name) != null) {
              break;
            }
          }
        }
        Assert.isTrue(paramName != null);
        FieldError fieldError =
            new FieldError( //
                "method", // 该出错字段所在的对象的名字;对于这类异常我们统一规定名字为method
                paramName, // 出错的字段的名字;取其参数名
                inv.getParameter(paramName), // 被拒绝的值
                true, // whether this error represents a binding failure (like a type mismatch);
                // else, it is a validation failure
                new String[] {e.getErrorCode()}, // "typeMismatch"
                new String[] {
                  inv.getParameter(paramName)
                }, // the array of arguments to be used to resolve this message
                null // the default message to be used to resolve this message
                );
        parameterBindingResult.addError(fieldError);
      } catch (Exception e) {
        // 什么错误呢?比如很有可能是构造对象不能成功导致的错误,没有默认构造函数、构造函数执行失败等等
        logger.error("", e);
        throw e;
      }
    }
    return parameters;
  }
  /**
   * Create an array of arguments to invoke a constructor or factory method, given the resolved
   * constructor argument values.
   */
  private ArgumentsHolder createArgumentArray(
      String beanName,
      RootBeanDefinition mbd,
      ConstructorArgumentValues resolvedValues,
      BeanWrapper bw,
      Class<?>[] paramTypes,
      String[] paramNames,
      Object methodOrCtor,
      boolean autowiring)
      throws UnsatisfiedDependencyException {

    String methodType = (methodOrCtor instanceof Constructor ? "constructor" : "factory method");
    TypeConverter converter =
        (this.beanFactory.getCustomTypeConverter() != null
            ? this.beanFactory.getCustomTypeConverter()
            : bw);

    ArgumentsHolder args = new ArgumentsHolder(paramTypes.length);
    Set<ConstructorArgumentValues.ValueHolder> usedValueHolders =
        new HashSet<ConstructorArgumentValues.ValueHolder>(paramTypes.length);
    Set<String> autowiredBeanNames = new LinkedHashSet<String>(4);

    for (int paramIndex = 0; paramIndex < paramTypes.length; paramIndex++) {
      Class<?> paramType = paramTypes[paramIndex];
      String paramName = (paramNames != null ? paramNames[paramIndex] : null);
      // Try to find matching constructor argument value, either indexed or generic.
      ConstructorArgumentValues.ValueHolder valueHolder =
          resolvedValues.getArgumentValue(paramIndex, paramType, paramName, usedValueHolders);
      // If we couldn't find a direct match and are not supposed to autowire,
      // let's try the next generic, untyped argument value as fallback:
      // it could match after type conversion (for example, String -> int).
      if (valueHolder == null && !autowiring) {
        valueHolder = resolvedValues.getGenericArgumentValue(null, null, usedValueHolders);
      }
      if (valueHolder != null) {
        // We found a potential match - let's give it a try.
        // Do not consider the same value definition multiple times!
        usedValueHolders.add(valueHolder);
        Object originalValue = valueHolder.getValue();
        Object convertedValue;
        if (valueHolder.isConverted()) {
          convertedValue = valueHolder.getConvertedValue();
          args.preparedArguments[paramIndex] = convertedValue;
        } else {
          ConstructorArgumentValues.ValueHolder sourceHolder =
              (ConstructorArgumentValues.ValueHolder) valueHolder.getSource();
          Object sourceValue = sourceHolder.getValue();
          try {
            convertedValue =
                converter.convertIfNecessary(
                    originalValue,
                    paramType,
                    MethodParameter.forMethodOrConstructor(methodOrCtor, paramIndex));
            // TODO re-enable once race condition has been found (SPR-7423)
            /*
            if (originalValue == sourceValue || sourceValue instanceof TypedStringValue) {
            	// Either a converted value or still the original one: store converted value.
            	sourceHolder.setConvertedValue(convertedValue);
            	args.preparedArguments[paramIndex] = convertedValue;
            }
            else {
            */
            args.resolveNecessary = true;
            args.preparedArguments[paramIndex] = sourceValue;
            // }
          } catch (TypeMismatchException ex) {
            throw new UnsatisfiedDependencyException(
                mbd.getResourceDescription(),
                beanName,
                paramIndex,
                paramType,
                "Could not convert "
                    + methodType
                    + " argument value of type ["
                    + ObjectUtils.nullSafeClassName(valueHolder.getValue())
                    + "] to required type ["
                    + paramType.getName()
                    + "]: "
                    + ex.getMessage());
          }
        }
        args.arguments[paramIndex] = convertedValue;
        args.rawArguments[paramIndex] = originalValue;
      } else {
        // No explicit match found: we're either supposed to autowire or
        // have to fail creating an argument array for the given constructor.
        if (!autowiring) {
          throw new UnsatisfiedDependencyException(
              mbd.getResourceDescription(),
              beanName,
              paramIndex,
              paramType,
              "Ambiguous "
                  + methodType
                  + " argument types - "
                  + "did you specify the correct bean references as "
                  + methodType
                  + " arguments?");
        }
        try {
          MethodParameter param = MethodParameter.forMethodOrConstructor(methodOrCtor, paramIndex);
          Object autowiredArgument =
              resolveAutowiredArgument(param, beanName, autowiredBeanNames, converter);
          args.rawArguments[paramIndex] = autowiredArgument;
          args.arguments[paramIndex] = autowiredArgument;
          args.preparedArguments[paramIndex] = new AutowiredArgumentMarker();
          args.resolveNecessary = true;
        } catch (BeansException ex) {
          throw new UnsatisfiedDependencyException(
              mbd.getResourceDescription(), beanName, paramIndex, paramType, ex);
        }
      }
    }

    for (String autowiredBeanName : autowiredBeanNames) {
      this.beanFactory.registerDependentBean(autowiredBeanName, beanName);
      if (this.beanFactory.logger.isDebugEnabled()) {
        this.beanFactory.logger.debug(
            "Autowiring by type from bean name '"
                + beanName
                + "' via "
                + methodType
                + " to bean named '"
                + autowiredBeanName
                + "'");
      }
    }

    return args;
  }
  /** Match the given qualifier annotation against the candidate bean definition. */
  protected boolean checkQualifier(
      BeanDefinitionHolder bdHolder, Annotation annotation, TypeConverter typeConverter) {

    Class<? extends Annotation> type = annotation.annotationType();
    RootBeanDefinition bd = (RootBeanDefinition) bdHolder.getBeanDefinition();
    AutowireCandidateQualifier qualifier = bd.getQualifier(type.getName());
    if (qualifier == null) {
      qualifier = bd.getQualifier(ClassUtils.getShortName(type));
    }
    if (qualifier == null) {
      Annotation targetAnnotation = null;
      if (bd.getResolvedFactoryMethod() != null) {
        targetAnnotation = AnnotationUtils.getAnnotation(bd.getResolvedFactoryMethod(), type);
      }
      if (targetAnnotation == null) {
        // look for matching annotation on the target class
        if (this.beanFactory != null) {
          Class<?> beanType = this.beanFactory.getType(bdHolder.getBeanName());
          if (beanType != null) {
            targetAnnotation =
                AnnotationUtils.getAnnotation(ClassUtils.getUserClass(beanType), type);
          }
        }
        if (targetAnnotation == null && bd.hasBeanClass()) {
          targetAnnotation =
              AnnotationUtils.getAnnotation(ClassUtils.getUserClass(bd.getBeanClass()), type);
        }
      }
      if (targetAnnotation != null && targetAnnotation.equals(annotation)) {
        return true;
      }
    }
    Map<String, Object> attributes = AnnotationUtils.getAnnotationAttributes(annotation);
    if (attributes.isEmpty() && qualifier == null) {
      // if no attributes, the qualifier must be present
      return false;
    }
    for (Map.Entry<String, Object> entry : attributes.entrySet()) {
      String attributeName = entry.getKey();
      Object expectedValue = entry.getValue();
      Object actualValue = null;
      // check qualifier first
      if (qualifier != null) {
        actualValue = qualifier.getAttribute(attributeName);
      }
      if (actualValue == null) {
        // fall back on bean definition attribute
        actualValue = bd.getAttribute(attributeName);
      }
      if (actualValue == null
          && attributeName.equals(AutowireCandidateQualifier.VALUE_KEY)
          && expectedValue instanceof String
          && bdHolder.matchesName((String) expectedValue)) {
        // fall back on bean name (or alias) match
        continue;
      }
      if (actualValue == null && qualifier != null) {
        // fall back on default, but only if the qualifier is present
        actualValue = AnnotationUtils.getDefaultValue(annotation, attributeName);
      }
      if (actualValue != null) {
        actualValue = typeConverter.convertIfNecessary(actualValue, expectedValue.getClass());
      }
      if (!expectedValue.equals(actualValue)) {
        return false;
      }
    }
    return true;
  }