diff --git a/spring-context/src/main/java/org/springframework/context/event/ApplicationListenerMethodAdapter.java b/spring-context/src/main/java/org/springframework/context/event/ApplicationListenerMethodAdapter.java index d60615b7af7c..e3446c83d142 100644 --- a/spring-context/src/main/java/org/springframework/context/event/ApplicationListenerMethodAdapter.java +++ b/spring-context/src/main/java/org/springframework/context/event/ApplicationListenerMethodAdapter.java @@ -67,6 +67,7 @@ * @author Juergen Hoeller * @author Sam Brannen * @author Sebastien Deleuze + * @author Yanming Zhou * @since 4.2 */ public class ApplicationListenerMethodAdapter implements GenericApplicationListener { @@ -177,13 +178,14 @@ public boolean supportsEventType(ResolvableType eventType) { return true; } if (PayloadApplicationEvent.class.isAssignableFrom(eventType.toClass())) { - if (eventType.hasUnresolvableGenerics()) { - return true; - } ResolvableType payloadType = eventType.as(PayloadApplicationEvent.class).getGeneric(); if (declaredEventType.isAssignableFrom(payloadType)) { return true; } + if (payloadType.resolve() == null) { + // Always accept such event when the type is erased + return true; + } } } return false; 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 d08be27dcb4e..4e4e1225ab6a 100644 --- a/spring-core/src/main/java/org/springframework/core/GenericTypeResolver.java +++ b/spring-core/src/main/java/org/springframework/core/GenericTypeResolver.java @@ -39,6 +39,7 @@ * @author Rob Harrop * @author Sam Brannen * @author Phillip Webb + * @author Yanming Zhou * @since 2.5.2 */ public final class GenericTypeResolver { @@ -167,7 +168,7 @@ public static Type resolveType(Type genericType, @Nullable Class contextClass else if (genericType instanceof ParameterizedType parameterizedType) { ResolvableType resolvedType = ResolvableType.forType(genericType); if (resolvedType.hasUnresolvableGenerics()) { - Class[] generics = new Class[parameterizedType.getActualTypeArguments().length]; + ResolvableType[] generics = new ResolvableType[parameterizedType.getActualTypeArguments().length]; Type[] typeArguments = parameterizedType.getActualTypeArguments(); ResolvableType contextType = ResolvableType.forClass(contextClass); for (int i = 0; i < typeArguments.length; i++) { @@ -175,14 +176,17 @@ else if (genericType instanceof ParameterizedType parameterizedType) { if (typeArgument instanceof TypeVariable typeVariable) { ResolvableType resolvedTypeArgument = resolveVariable(typeVariable, contextType); if (resolvedTypeArgument != ResolvableType.NONE) { - generics[i] = resolvedTypeArgument.resolve(); + generics[i] = resolvedTypeArgument; } else { - generics[i] = ResolvableType.forType(typeArgument).resolve(); + generics[i] = ResolvableType.forType(typeArgument); } } + else if (typeArgument instanceof ParameterizedType) { + generics[i] = ResolvableType.forType(resolveType(typeArgument, contextClass)); + } else { - generics[i] = ResolvableType.forType(typeArgument).resolve(); + generics[i] = ResolvableType.forType(typeArgument); } } Class rawClass = resolvedType.getRawClass(); 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 510b191c9a5a..fc70a6c9ebc2 100644 --- a/spring-core/src/main/java/org/springframework/core/ResolvableType.java +++ b/spring-core/src/main/java/org/springframework/core/ResolvableType.java @@ -70,6 +70,7 @@ * @author Phillip Webb * @author Juergen Hoeller * @author Stephane Nicoll + * @author Yanming Zhou * @since 4.0 * @see #forField(Field) * @see #forMethodParameter(Method, int) @@ -572,7 +573,7 @@ public boolean hasUnresolvableGenerics() { private boolean determineUnresolvableGenerics() { ResolvableType[] generics = getGenerics(); for (ResolvableType generic : generics) { - if (generic.isUnresolvableTypeVariable() || generic.isWildcardWithoutBounds()) { + if (generic.isUnresolvableTypeVariable() || generic.isWildcardWithoutBounds() || generic.hasUnresolvableGenerics()) { return true; } } 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 403c11e7ffec..b6e1c2cfdf9b 100644 --- a/spring-core/src/test/java/org/springframework/core/GenericTypeResolverTests.java +++ b/spring-core/src/test/java/org/springframework/core/GenericTypeResolverTests.java @@ -39,6 +39,7 @@ * @author Sam Brannen * @author Sebastien Deleuze * @author Stephane Nicoll + * @author Yanming Zhou */ @SuppressWarnings({"unchecked", "rawtypes"}) class GenericTypeResolverTests { @@ -203,6 +204,13 @@ public void resolveMethodParameterWithNestedGenerics() { assertThat(resolvedType).isEqualTo(reference.getType()); } + @Test + void resolveNestedTypeVariable() throws Exception { + Type resolved = resolveType(ListOfListSupplier.class.getMethod("get").getGenericReturnType(), + StringListOfListSupplier.class); + assertThat(ResolvableType.forType(resolved).getGeneric(0).getGeneric(0).resolve()).isEqualTo(String.class); + } + private static Method method(Class target, String methodName, Class... parameterTypes) { Method method = findMethod(target, methodName, parameterTypes); assertThat(method).describedAs(target.getName() + "#" + methodName).isNotNull(); @@ -402,5 +410,14 @@ public void nestedGenerics(List> input) { } } + public interface ListOfListSupplier { + + List> get(); + + } + + public interface StringListOfListSupplier extends ListOfListSupplier { + + } } 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 a1388be50d96..3b8088c94515 100644 --- a/spring-core/src/test/java/org/springframework/core/ResolvableTypeTests.java +++ b/spring-core/src/test/java/org/springframework/core/ResolvableTypeTests.java @@ -66,6 +66,7 @@ * @author Phillip Webb * @author Juergen Hoeller * @author Sebastien Deleuze + * @author Yanming Zhou */ @SuppressWarnings("rawtypes") @ExtendWith(MockitoExtension.class) @@ -1314,6 +1315,12 @@ void hasUnresolvableGenericsWhenExtends() throws Exception { assertThat(type.hasUnresolvableGenerics()).isTrue(); } + @Test + void hasUnresolvableGenericsWhenNested() throws Exception { + ResolvableType type = ResolvableType.forMethodReturnType(ListOfListSupplier.class.getMethod("get")); + assertThat(type.hasUnresolvableGenerics()).isTrue(); + } + @Test void spr11219() throws Exception { ResolvableType type = ResolvableType.forField(BaseProvider.class.getField("stuff"), BaseProvider.class); @@ -1617,6 +1624,12 @@ interface ListOfGenericArray extends List[]> { } + public interface ListOfListSupplier { + + List> get(); + + } + static class EnclosedInParameterizedType { static class InnerRaw {