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 { - - public void upperBound(List list) { - } - - public void upperBoundWithResolvedType(List list) { - } - - public void lowerBound(List list) { - } - - public void lowerBoundWithResolvedType(List list) { - } - - public void unbounded(List list) { - } } public class MySimpleSuperclassType extends MySuperclassType {