Aligned with refinements in 3.2.x branch

Issue: SPR-11034
This commit is contained in:
Juergen Hoeller 2013-10-27 23:00:43 +01:00 committed by unknown
parent 24dfe8ec19
commit 56dfcd153e
2 changed files with 36 additions and 17 deletions

View File

@ -61,7 +61,7 @@ public class TypedStringValue implements BeanMetadataElement {
* @param value the String value * @param value the String value
* @param targetType the type to convert to * @param targetType the type to convert to
*/ */
public TypedStringValue(String value, Class targetType) { public TypedStringValue(String value, Class<?> targetType) {
setValue(value); setValue(value);
setTargetType(targetType); setTargetType(targetType);
} }
@ -101,7 +101,7 @@ public class TypedStringValue implements BeanMetadataElement {
* for example in BeanFactoryPostProcessors. * for example in BeanFactoryPostProcessors.
* @see PropertyPlaceholderConfigurer * @see PropertyPlaceholderConfigurer
*/ */
public void setTargetType(Class targetType) { public void setTargetType(Class<?> targetType) {
Assert.notNull(targetType, "'targetType' must not be null"); Assert.notNull(targetType, "'targetType' must not be null");
this.targetType = targetType; this.targetType = targetType;
} }

View File

@ -31,6 +31,7 @@ import java.util.Arrays;
import java.util.Comparator; import java.util.Comparator;
import java.util.Set; import java.util.Set;
import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.factory.ObjectFactory; import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.TypedStringValue; import org.springframework.beans.factory.config.TypedStringValue;
import org.springframework.util.Assert; import org.springframework.util.Assert;
@ -195,8 +196,8 @@ abstract class AutowireUtils {
TypeVariable<Method>[] declaredTypeVariables = method.getTypeParameters(); TypeVariable<Method>[] declaredTypeVariables = method.getTypeParameters();
Type genericReturnType = method.getGenericReturnType(); Type genericReturnType = method.getGenericReturnType();
Type[] methodArgumentTypes = method.getGenericParameterTypes(); Type[] methodParameterTypes = method.getGenericParameterTypes();
Assert.isTrue(args.length == methodArgumentTypes.length, "Argument array does not match parameter count"); 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 // Ensure that the type variable (e.g., T) is declared directly on the method
// itself (e.g., via <T>), not on the enclosing class or interface. // itself (e.g., via <T>), not on the enclosing class or interface.
@ -209,17 +210,33 @@ abstract class AutowireUtils {
} }
if (locallyDeclaredTypeVariableMatchesReturnType) { if (locallyDeclaredTypeVariableMatchesReturnType) {
for (int i = 0; i < methodArgumentTypes.length; i++) { for (int i = 0; i < methodParameterTypes.length; i++) {
Type currentMethodArgumentType = methodArgumentTypes[i]; Type methodParameterType = methodParameterTypes[i];
if (currentMethodArgumentType.equals(genericReturnType)) { Object arg = args[i];
return args[i].getClass(); if (methodParameterType.equals(genericReturnType)) {
if (arg instanceof TypedStringValue) {
TypedStringValue typedValue = ((TypedStringValue) arg);
if (typedValue.hasTargetType()) {
return typedValue.getTargetType();
} }
if (currentMethodArgumentType instanceof ParameterizedType) { try {
ParameterizedType parameterizedType = (ParameterizedType) currentMethodArgumentType; 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();
}
else if (methodParameterType instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) methodParameterType;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
for (Type typeArg : actualTypeArguments) { for (Type typeArg : actualTypeArguments) {
if (typeArg.equals(genericReturnType)) { if (typeArg.equals(genericReturnType)) {
Object arg = args[i];
if (arg instanceof Class) { if (arg instanceof Class) {
return (Class<?>) arg; return (Class<?>) arg;
} }
@ -229,7 +246,11 @@ abstract class AutowireUtils {
className = (String) arg; className = (String) arg;
} }
else if (arg instanceof TypedStringValue) { 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) { if (className != null) {
try { try {
@ -240,7 +261,6 @@ abstract class AutowireUtils {
"Could not resolve specified class name argument [" + arg + "]", ex); "Could not resolve specified class name argument [" + arg + "]", ex);
} }
} }
else {
// Consider adding logic to determine the class of the typeArg, if possible. // Consider adding logic to determine the class of the typeArg, if possible.
// For now, just fall back... // For now, just fall back...
return method.getReturnType(); return method.getReturnType();
@ -250,7 +270,6 @@ abstract class AutowireUtils {
} }
} }
} }
}
// Fall back... // Fall back...
return method.getReturnType(); return method.getReturnType();