Browse Source

Accept assignable match for covariant return type

See gh-35936

(cherry picked from commit df27627516)
6.2.x
Juergen Hoeller 1 week ago
parent
commit
ad849fb3a2
  1. 8
      spring-core/src/main/java/org/springframework/core/BridgeMethodResolver.java
  2. 38
      spring-core/src/test/java/org/springframework/core/BridgeMethodResolverTests.java

8
spring-core/src/main/java/org/springframework/core/BridgeMethodResolver.java

@ -202,15 +202,15 @@ public final class BridgeMethodResolver { @@ -202,15 +202,15 @@ public final class BridgeMethodResolver {
private static boolean checkResolvedTypeMatch(Method genericMethod, Method candidateMethod, Class<?> clazz) {
// First, compare return type.
ResolvableType genericReturnType = ResolvableType.forMethodReturnType(genericMethod, clazz);
if (!ClassUtils.resolvePrimitiveIfNecessary(candidateMethod.getReturnType()).equals(
ClassUtils.resolvePrimitiveIfNecessary(genericReturnType.toClass()))) {
if (!ClassUtils.resolvePrimitiveIfNecessary(genericReturnType.toClass()).isAssignableFrom(
ClassUtils.resolvePrimitiveIfNecessary(candidateMethod.getReturnType()))) {
return false;
}
Class<?>[] candidateParameters = candidateMethod.getParameterTypes();
for (int i = 0; i < candidateParameters.length; i++) {
ResolvableType genericParameter = ResolvableType.forMethodParameter(genericMethod, i, clazz);
if (!ClassUtils.resolvePrimitiveIfNecessary(candidateParameters[i]).equals(
ClassUtils.resolvePrimitiveIfNecessary(genericParameter.toClass()))) {
if (!ClassUtils.resolvePrimitiveIfNecessary(genericParameter.toClass()).equals(
ClassUtils.resolvePrimitiveIfNecessary(candidateParameters[i]))) {
return false;
}
}

38
spring-core/src/test/java/org/springframework/core/BridgeMethodResolverTests.java

@ -113,6 +113,14 @@ class BridgeMethodResolverTests { @@ -113,6 +113,14 @@ class BridgeMethodResolverTests {
}
}
@Test
void findBridgedMethodForCovariantReturnType() throws Exception {
Method originalMethod = OuterSubclass.class.getDeclaredMethod("getInner");
for (Method method: OuterSubclass.class.getDeclaredMethods()) {
assertThat(BridgeMethodResolver.findBridgedMethod(method)).isEqualTo(originalMethod);
}
}
@Test
void findBridgedMethodInHierarchyWithBoundedGenerics() throws Exception {
Method originalMethod = Bar.class.getDeclaredMethod("someMethod", Object.class, Object.class);
@ -425,6 +433,7 @@ class BridgeMethodResolverTests { @@ -425,6 +433,7 @@ class BridgeMethodResolverTests {
public abstract static class SubBar<T extends StringProducer> extends InterBar<T> {
}
public interface StringProducer extends CharSequence {
}
@ -506,6 +515,31 @@ class BridgeMethodResolverTests { @@ -506,6 +515,31 @@ class BridgeMethodResolverTests {
}
static class Outer {
Inner getInner() {
return new Inner();
}
}
static class OuterSubclass extends Outer {
@Override
InnerSubclass getInner() {
return new InnerSubclass();
}
}
static class Inner {
}
static class InnerSubclass extends Inner {
}
public static class Enclosing<T> {
public class Enclosed<S> {
@ -899,22 +933,18 @@ class BridgeMethodResolverTests { @@ -899,22 +933,18 @@ class BridgeMethodResolverTests {
public interface MessageBroadcaster extends Receiver<MessageEvent> {
}
public static class RemovedMessageEvent extends MessageEvent {
}
public static class NewMessageEvent extends MessageEvent {
}
public static class ModifiedMessageEvent extends MessageEvent {
}

Loading…
Cancel
Save