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); }
@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; }