diff --git a/spring-core/src/main/java/org/springframework/core/GenericTypeResolver.java b/spring-core/src/main/java/org/springframework/core/GenericTypeResolver.java index c27a23cd07e..9e4a9e381a8 100644 --- a/spring-core/src/main/java/org/springframework/core/GenericTypeResolver.java +++ b/spring-core/src/main/java/org/springframework/core/GenericTypeResolver.java @@ -180,7 +180,7 @@ public final class GenericTypeResolver { generics[i] = resolvedTypeArgument; } else { - generics[i] = ResolvableType.forType(typeArgument).resolveType(); + generics[i] = ResolvableType.forType(typeArgument); } } else if (typeArgument instanceof ParameterizedType) { @@ -226,7 +226,7 @@ public final class GenericTypeResolver { return resolvedType; } } - return ResolvableType.NONE; + return ResolvableType.forVariableBounds(typeVariable); } /** diff --git a/spring-core/src/main/java/org/springframework/core/ResolvableType.java b/spring-core/src/main/java/org/springframework/core/ResolvableType.java index 30c3c947d72..594beef070a 100644 --- a/spring-core/src/main/java/org/springframework/core/ResolvableType.java +++ b/spring-core/src/main/java/org/springframework/core/ResolvableType.java @@ -953,14 +953,6 @@ public class ResolvableType implements Serializable { return NONE; } - @Nullable - private Type resolveBounds(Type[] bounds) { - if (bounds.length == 0 || bounds[0] == Object.class) { - return null; - } - return bounds[0]; - } - @Nullable private ResolvableType resolveVariable(TypeVariable> variable) { if (this.type instanceof TypeVariable) { @@ -1463,6 +1455,24 @@ public class ResolvableType implements Serializable { return new ResolvableType(arrayType, componentType, null, null); } + /** + * Return a {@code ResolvableType} for the bounds of the specified {@link TypeVariable}. + * @param typeVariable the type variable + * @return a {@code ResolvableType} for the specified bounds + * @since 6.2.3 + */ + static ResolvableType forVariableBounds(TypeVariable> typeVariable) { + return forType(resolveBounds(typeVariable.getBounds())); + } + + @Nullable + private static Type resolveBounds(Type[] bounds) { + if (bounds.length == 0 || bounds[0] == Object.class) { + return null; + } + return bounds[0]; + } + /** * Return a {@code ResolvableType} for the specified {@link Type}. *
Note: The resulting {@code ResolvableType} instance may not be {@link Serializable}. @@ -1491,7 +1501,6 @@ public class ResolvableType implements Serializable { return forType(type, variableResolver); } - /** * Return a {@code ResolvableType} for the specified {@link ParameterizedTypeReference}. *
Note: The resulting {@code ResolvableType} instance may not be {@link Serializable}.
diff --git a/spring-core/src/test/java/org/springframework/core/GenericTypeResolverTests.java b/spring-core/src/test/java/org/springframework/core/GenericTypeResolverTests.java
index 1f80cc6c343..fcfff993433 100644
--- a/spring-core/src/test/java/org/springframework/core/GenericTypeResolverTests.java
+++ b/spring-core/src/test/java/org/springframework/core/GenericTypeResolverTests.java
@@ -212,19 +212,27 @@ class GenericTypeResolverTests {
}
@Test
- void resolvedTypeWithBase() {
- Type type = method(WithBaseTypes.class, "get").getGenericReturnType();
- Type resolvedType = resolveType(type, WithBaseTypes.class);
+ void resolveTypeWithElementBounds() {
+ Type type = method(WithElementBounds.class, "get").getGenericReturnType();
+ Type resolvedType = resolveType(type, WithElementBounds.class);
ParameterizedTypeReference> reference = new ParameterizedTypeReference<>() {};
assertThat(resolvedType).isEqualTo(reference.getType());
}
+ @Test
+ void resolveTypeWithUnresolvableElement() {
+ Type type = method(WithUnresolvableElement.class, "get").getGenericReturnType();
+ Type resolvedType = resolveType(type, WithUnresolvableElement.class);
+ assertThat(resolvedType.toString()).isEqualTo("java.util.List