diff --git a/org.springframework.core/src/main/java/org/springframework/core/GenericTypeResolver.java b/org.springframework.core/src/main/java/org/springframework/core/GenericTypeResolver.java
index de2502e962f..25b1d37b295 100644
--- a/org.springframework.core/src/main/java/org/springframework/core/GenericTypeResolver.java
+++ b/org.springframework.core/src/main/java/org/springframework/core/GenericTypeResolver.java
@@ -24,6 +24,8 @@ import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
+import java.lang.reflect.WildcardType;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -102,6 +104,35 @@ public abstract class GenericTypeResolver {
return (rawType instanceof Class ? (Class) rawType : method.getReturnType());
}
+ /**
+ * Resolve the single type argument of the given generic interface against the given
+ * target method which is assumed to return the given interface or an implementation
+ * of it.
+ * @param method the target method to check the return type of
+ * @param genericIfc the generic interface or superclass to resolve the type argument from
+ * @return the resolved parameter type of the method return type, or null
+ * if not resolvable or if the single argument is of type {@link WildcardType}.
+ */
+ public static Class> resolveReturnTypeArgument(Method method, Class> genericIfc) {
+ Type returnType = method.getReturnType();
+ Type genericReturnType = method.getGenericReturnType();
+ ParameterizedType targetType;
+ if (returnType.equals(genericIfc)) {
+ if (genericReturnType instanceof ParameterizedType) {
+ targetType = (ParameterizedType)genericReturnType;
+ Type[] actualTypeArguments = targetType.getActualTypeArguments();
+ Type typeArg = actualTypeArguments[0];
+ if (!(typeArg instanceof WildcardType)) {
+ return (Class>)typeArg;
+ }
+ }
+ else {
+ return null;
+ }
+ }
+ return GenericTypeResolver.resolveTypeArgument((Class>)returnType, genericIfc);
+ }
+
/**
* Resolve the single type argument of the given generic interface against
* the given target class which is assumed to implement the generic interface
diff --git a/org.springframework.core/src/test/java/org/springframework/core/GenericTypeResolverTests.java b/org.springframework.core/src/test/java/org/springframework/core/GenericTypeResolverTests.java
index df595e3f2c0..e419c0bc1f6 100644
--- a/org.springframework.core/src/test/java/org/springframework/core/GenericTypeResolverTests.java
+++ b/org.springframework.core/src/test/java/org/springframework/core/GenericTypeResolverTests.java
@@ -20,6 +20,7 @@ import java.util.Collection;
import static org.junit.Assert.*;
import org.junit.Test;
+import org.springframework.util.ReflectionUtils;
/**
* @author Juergen Hoeller
@@ -46,6 +47,14 @@ public class GenericTypeResolverTests {
assertEquals(Collection.class, GenericTypeResolver.resolveTypeArgument(MyCollectionSuperclassType.class, MySuperclassType.class));
}
+ @Test
+ public void testMethodReturnType() {
+ assertEquals(Integer.class, GenericTypeResolver.resolveReturnTypeArgument(ReflectionUtils.findMethod(MyTypeWithMethods.class, "integer"), MyInterfaceType.class));
+ assertEquals(String.class, GenericTypeResolver.resolveReturnTypeArgument(ReflectionUtils.findMethod(MyTypeWithMethods.class, "string"), MyInterfaceType.class));
+ assertEquals(null, GenericTypeResolver.resolveReturnTypeArgument(ReflectionUtils.findMethod(MyTypeWithMethods.class, "raw"), MyInterfaceType.class));
+ assertEquals(null, GenericTypeResolver.resolveReturnTypeArgument(ReflectionUtils.findMethod(MyTypeWithMethods.class, "object"), MyInterfaceType.class));
+ }
+
public interface MyInterfaceType {
}
@@ -66,4 +75,12 @@ public class GenericTypeResolverTests {
public class MyCollectionSuperclassType extends MySuperclassType> {
}
+ public class MyTypeWithMethods {
+ public MyInterfaceType integer() { return null; }
+ public MySimpleInterfaceType string() { return null; }
+ public Object object() { return null; }
+ @SuppressWarnings("rawtypes")
+ public MyInterfaceType raw() { return null; }
+ }
+
}