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 95ce4f1f28..d08be27dcb 100644 --- a/spring-core/src/main/java/org/springframework/core/GenericTypeResolver.java +++ b/spring-core/src/main/java/org/springframework/core/GenericTypeResolver.java @@ -39,7 +39,6 @@ import org.springframework.util.ConcurrentReferenceHashMap; * @author Rob Harrop * @author Sam Brannen * @author Phillip Webb - * @author Sebastien Deleuze * @since 2.5.2 */ public final class GenericTypeResolver { @@ -167,30 +166,29 @@ public final class GenericTypeResolver { } else if (genericType instanceof ParameterizedType parameterizedType) { ResolvableType resolvedType = ResolvableType.forType(genericType); - Class>[] generics = new Class>[parameterizedType.getActualTypeArguments().length]; - Type[] typeArguments = parameterizedType.getActualTypeArguments(); - ResolvableType contextType = ResolvableType.forClass(contextClass); - for (int i = 0; i < typeArguments.length; i++) { - Type typeArgument = typeArguments[i]; - if (typeArgument instanceof TypeVariable> typeVariable) { - ResolvableType resolvedTypeArgument = resolveVariable(typeVariable, contextType); - if (resolvedTypeArgument != ResolvableType.NONE) { - generics[i] = resolvedTypeArgument.resolve(); + if (resolvedType.hasUnresolvableGenerics()) { + Class>[] generics = new Class>[parameterizedType.getActualTypeArguments().length]; + Type[] typeArguments = parameterizedType.getActualTypeArguments(); + ResolvableType contextType = ResolvableType.forClass(contextClass); + for (int i = 0; i < typeArguments.length; i++) { + Type typeArgument = typeArguments[i]; + if (typeArgument instanceof TypeVariable> typeVariable) { + ResolvableType resolvedTypeArgument = resolveVariable(typeVariable, contextType); + if (resolvedTypeArgument != ResolvableType.NONE) { + generics[i] = resolvedTypeArgument.resolve(); + } + else { + generics[i] = ResolvableType.forType(typeArgument).resolve(); + } } else { generics[i] = ResolvableType.forType(typeArgument).resolve(); } } - else if (typeArgument instanceof WildcardType wildcardType) { - generics[i] = resolveWildcard(wildcardType, contextType).resolve(); + Class> rawClass = resolvedType.getRawClass(); + if (rawClass != null) { + return ResolvableType.forClassWithGenerics(rawClass, generics).getType(); } - else { - generics[i] = ResolvableType.forType(typeArgument).resolve(); - } - } - Class> rawClass = resolvedType.getRawClass(); - if (rawClass != null) { - return ResolvableType.forClassWithGenerics(rawClass, generics).getType(); } } } @@ -226,26 +224,6 @@ public final class GenericTypeResolver { return ResolvableType.NONE; } - private static ResolvableType resolveWildcard(WildcardType wildcardType, ResolvableType contextType) { - for (Type bound : wildcardType.getUpperBounds()) { - if (bound instanceof TypeVariable> typeVariable) { - ResolvableType resolvedTypeArgument = resolveVariable(typeVariable, contextType); - if (resolvedTypeArgument != ResolvableType.NONE) { - return resolvedTypeArgument; - } - } - } - for (Type bound : wildcardType.getLowerBounds()) { - if (bound instanceof TypeVariable> typeVariable) { - ResolvableType resolvedTypeArgument = resolveVariable(typeVariable, contextType); - if (resolvedTypeArgument != ResolvableType.NONE) { - return resolvedTypeArgument; - } - } - } - return ResolvableType.forType(wildcardType); - } - /** * Resolve the specified generic type against the given TypeVariable map. *
Used by Spring Data.
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 0b04f859d5..2c049da847 100644
--- a/spring-core/src/test/java/org/springframework/core/GenericTypeResolverTests.java
+++ b/spring-core/src/test/java/org/springframework/core/GenericTypeResolverTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2023 the original author or authors.
+ * Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -194,58 +194,6 @@ class GenericTypeResolverTests {
assertThat(resolved).isEqualTo(E.class);
}
- @Test
- void resolveWildcardTypeWithUpperBound() {
- Method method = method(MySimpleSuperclassType.class, "upperBound", List.class);
- Type resolved = resolveType(method.getGenericParameterTypes()[0], MySimpleSuperclassType.class);
- ResolvableType resolvableType = ResolvableType.forType(resolved);
- assertThat(resolvableType.hasUnresolvableGenerics()).isFalse();
- assertThat(resolvableType.resolveGenerics()).containsExactly(String.class);
- }
-
- @Test
- void resolveWildcardTypeWithUpperBoundWithResolvedType() {
- Method method = method(MySimpleSuperclassType.class, "upperBoundWithResolvedType", List.class);
- Type resolved = resolveType(method.getGenericParameterTypes()[0], MySimpleSuperclassType.class);
- ResolvableType resolvableType = ResolvableType.forType(resolved);
- assertThat(resolvableType.hasUnresolvableGenerics()).isFalse();
- assertThat(resolvableType.resolveGenerics()).containsExactly(Integer.class);
- }
-
- @Test
- void resolveWildcardTypeWithLowerBound() {
- Method method = method(MySimpleSuperclassType.class, "lowerBound", List.class);
- Type resolved = resolveType(method.getGenericParameterTypes()[0], MySimpleSuperclassType.class);
- ResolvableType resolvableType = ResolvableType.forType(resolved);
- assertThat(resolvableType.hasUnresolvableGenerics()).isFalse();
- assertThat(resolvableType.resolveGenerics()).containsExactly(String.class);
- }
-
- @Test
- void resolveWildcardTypeWithLowerBoundWithResolvedType() {
- Method method = method(MySimpleSuperclassType.class, "lowerBoundWithResolvedType", List.class);
- Type resolved = resolveType(method.getGenericParameterTypes()[0], MySimpleSuperclassType.class);
- ResolvableType resolvableType = ResolvableType.forType(resolved);
- assertThat(resolvableType.hasUnresolvableGenerics()).isFalse();
- assertThat(resolvableType.resolveGenerics()).containsExactly(Integer.class);
- }
-
- @Test
- void resolveWildcardTypeWithUnbounded() {
- Method method = method(MySimpleSuperclassType.class, "unbounded", List.class);
- Type resolved = resolveType(method.getGenericParameterTypes()[0], MySimpleSuperclassType.class);
- ResolvableType resolvableType = ResolvableType.forType(resolved);
- assertThat(resolvableType.hasUnresolvableGenerics()).isFalse();
- assertThat(resolvableType.resolveGenerics()).containsExactly(Object.class);
- }
-
- @Test // gh-28904
- void resolveGenericWithDifferentInterfaceOrder() {
- Type f = First.class.getTypeParameters()[0];
- assertThat(resolveType(f, FirstSecondService.class)).isEqualTo(Integer.class);
- assertThat(resolveType(f, SecondFirstService.class)).isEqualTo(Integer.class);
- }
-
private static Method method(Class> target, String methodName, Class>... parameterTypes) {
Method method = findMethod(target, methodName, parameterTypes);
assertThat(method).describedAs(target.getName() + "#" + methodName).isNotNull();
@@ -268,21 +216,6 @@ class GenericTypeResolverTests {
}
public abstract class MySuperclassType