From 56dfcd153e1648f8ce023f0becc02cd2c5a8fbcc Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Sun, 27 Oct 2013 23:00:43 +0100 Subject: [PATCH] Aligned with refinements in 3.2.x branch Issue: SPR-11034 --- .../factory/config/TypedStringValue.java | 4 +- .../beans/factory/support/AutowireUtils.java | 49 +++++++++++++------ 2 files changed, 36 insertions(+), 17 deletions(-) diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/config/TypedStringValue.java b/spring-beans/src/main/java/org/springframework/beans/factory/config/TypedStringValue.java index a9099a1974..bf107e6b1f 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/config/TypedStringValue.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/config/TypedStringValue.java @@ -61,7 +61,7 @@ public class TypedStringValue implements BeanMetadataElement { * @param value the String value * @param targetType the type to convert to */ - public TypedStringValue(String value, Class targetType) { + public TypedStringValue(String value, Class targetType) { setValue(value); setTargetType(targetType); } @@ -101,7 +101,7 @@ public class TypedStringValue implements BeanMetadataElement { * for example in BeanFactoryPostProcessors. * @see PropertyPlaceholderConfigurer */ - public void setTargetType(Class targetType) { + public void setTargetType(Class targetType) { Assert.notNull(targetType, "'targetType' must not be null"); this.targetType = targetType; } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireUtils.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireUtils.java index e83426e76a..2e25d1904a 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireUtils.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireUtils.java @@ -31,6 +31,7 @@ import java.util.Arrays; import java.util.Comparator; import java.util.Set; +import org.springframework.beans.BeanMetadataElement; import org.springframework.beans.factory.ObjectFactory; import org.springframework.beans.factory.config.TypedStringValue; import org.springframework.util.Assert; @@ -195,8 +196,8 @@ abstract class AutowireUtils { TypeVariable[] declaredTypeVariables = method.getTypeParameters(); Type genericReturnType = method.getGenericReturnType(); - Type[] methodArgumentTypes = method.getGenericParameterTypes(); - Assert.isTrue(args.length == methodArgumentTypes.length, "Argument array does not match parameter count"); + Type[] methodParameterTypes = method.getGenericParameterTypes(); + Assert.isTrue(args.length == methodParameterTypes.length, "Argument array does not match parameter count"); // Ensure that the type variable (e.g., T) is declared directly on the method // itself (e.g., via ), not on the enclosing class or interface. @@ -209,17 +210,33 @@ abstract class AutowireUtils { } if (locallyDeclaredTypeVariableMatchesReturnType) { - for (int i = 0; i < methodArgumentTypes.length; i++) { - Type currentMethodArgumentType = methodArgumentTypes[i]; - if (currentMethodArgumentType.equals(genericReturnType)) { - return args[i].getClass(); + for (int i = 0; i < methodParameterTypes.length; i++) { + Type methodParameterType = methodParameterTypes[i]; + Object arg = args[i]; + if (methodParameterType.equals(genericReturnType)) { + if (arg instanceof TypedStringValue) { + TypedStringValue typedValue = ((TypedStringValue) arg); + if (typedValue.hasTargetType()) { + return typedValue.getTargetType(); + } + try { + return typedValue.resolveTargetType(classLoader); + } + catch (ClassNotFoundException ex) { + throw new IllegalStateException("Failed to resolve typed value", ex); + } + } + // Only consider argument type if it is a simple value... + if (arg != null && !(arg instanceof BeanMetadataElement)) { + return arg.getClass(); + } + return method.getReturnType(); } - if (currentMethodArgumentType instanceof ParameterizedType) { - ParameterizedType parameterizedType = (ParameterizedType) currentMethodArgumentType; + else if (methodParameterType instanceof ParameterizedType) { + ParameterizedType parameterizedType = (ParameterizedType) methodParameterType; Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); for (Type typeArg : actualTypeArguments) { if (typeArg.equals(genericReturnType)) { - Object arg = args[i]; if (arg instanceof Class) { return (Class) arg; } @@ -229,7 +246,11 @@ abstract class AutowireUtils { className = (String) arg; } else if (arg instanceof TypedStringValue) { - className = ((TypedStringValue) arg).getValue(); + TypedStringValue typedValue = ((TypedStringValue) arg); + String targetTypeName = typedValue.getTargetTypeName(); + if (targetTypeName == null || Class.class.getName().equals(targetTypeName)) { + className = typedValue.getValue(); + } } if (className != null) { try { @@ -240,11 +261,9 @@ abstract class AutowireUtils { "Could not resolve specified class name argument [" + arg + "]", ex); } } - else { - // Consider adding logic to determine the class of the typeArg, if possible. - // For now, just fall back... - return method.getReturnType(); - } + // Consider adding logic to determine the class of the typeArg, if possible. + // For now, just fall back... + return method.getReturnType(); } } }