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 720e4eb56e77..994a395cf7d0 100644 --- a/spring-core/src/main/java/org/springframework/core/ResolvableType.java +++ b/spring-core/src/main/java/org/springframework/core/ResolvableType.java @@ -873,6 +873,12 @@ private ResolvableType resolveVariable(TypeVariable variable) { return forType(ownerType, this.variableResolver).resolveVariable(variable); } } + if (this.type instanceof WildcardType) { + ResolvableType resolved = resolveType().resolveVariable(variable); + if (resolved != null) { + return resolved; + } + } if (this.variableResolver != null) { return this.variableResolver.resolveVariable(variable); } diff --git a/spring-core/src/test/java/org/springframework/core/ResolvableTypeTests.java b/spring-core/src/test/java/org/springframework/core/ResolvableTypeTests.java index 27182ecfb16d..7a781bb7e7d1 100644 --- a/spring-core/src/test/java/org/springframework/core/ResolvableTypeTests.java +++ b/spring-core/src/test/java/org/springframework/core/ResolvableTypeTests.java @@ -688,6 +688,13 @@ void resolveBoundedTypeVariableResult() throws Exception { assertThat(type.resolve()).isEqualTo(CharSequence.class); } + + @Test + void resolveBoundedTypeVariableWildcardResult() throws Exception { + ResolvableType type = ResolvableType.forMethodReturnType(Methods.class.getMethod("boundedTypeVaraibleWildcardResult")); + assertThat(type.getGeneric(1).asCollection().resolveGeneric()).isEqualTo(CharSequence.class); + } + @Test void resolveVariableNotFound() throws Exception { ResolvableType type = ResolvableType.forMethodReturnType(Methods.class.getMethod("typedReturn")); @@ -1417,6 +1424,8 @@ interface Methods { R boundedTypeVaraibleResult(); + Map> boundedTypeVaraibleWildcardResult(); + void nested(Map, Map> p); void typedParameter(T p);