diff --git a/spring-core/src/main/java/org/springframework/core/BridgeMethodResolver.java b/spring-core/src/main/java/org/springframework/core/BridgeMethodResolver.java index f399f3e270c1..cc1f351175cd 100644 --- a/spring-core/src/main/java/org/springframework/core/BridgeMethodResolver.java +++ b/spring-core/src/main/java/org/springframework/core/BridgeMethodResolver.java @@ -110,7 +110,7 @@ private static Method resolveBridgeMethod(Method bridgeMethod, Class targetCl ReflectionUtils.doWithMethods(targetClass, candidateMethods::add, filter); if (!candidateMethods.isEmpty()) { bridgedMethod = (candidateMethods.size() == 1 ? candidateMethods.get(0) : - searchCandidates(candidateMethods, bridgeMethod, targetClass)); + searchCandidates(candidateMethods, bridgeMethod)); } if (bridgedMethod == null) { // A bridge method was passed in but we couldn't find the bridged method. @@ -141,14 +141,14 @@ private static boolean isBridgedCandidateFor(Method candidateMethod, Method brid * @return the bridged method, or {@code null} if none found */ @Nullable - private static Method searchCandidates(List candidateMethods, Method bridgeMethod, Class targetClass) { + private static Method searchCandidates(List candidateMethods, Method bridgeMethod) { if (candidateMethods.isEmpty()) { return null; } Method previousMethod = null; boolean sameSig = true; for (Method candidateMethod : candidateMethods) { - if (isBridgeMethodFor(bridgeMethod, candidateMethod, targetClass)) { + if (isBridgeMethodFor(bridgeMethod, candidateMethod, bridgeMethod.getDeclaringClass())) { return candidateMethod; } else if (previousMethod != null) { @@ -164,12 +164,12 @@ else if (previousMethod != null) { * Determines whether the bridge {@link Method} is the bridge for the * supplied candidate {@link Method}. */ - static boolean isBridgeMethodFor(Method bridgeMethod, Method candidateMethod, Class targetClass) { - if (isResolvedTypeMatch(candidateMethod, bridgeMethod, targetClass)) { + static boolean isBridgeMethodFor(Method bridgeMethod, Method candidateMethod, Class declaringClass) { + if (isResolvedTypeMatch(candidateMethod, bridgeMethod, declaringClass)) { return true; } Method method = findGenericDeclaration(bridgeMethod); - return (method != null && isResolvedTypeMatch(method, candidateMethod, targetClass)); + return (method != null && isResolvedTypeMatch(method, candidateMethod, declaringClass)); } /** @@ -178,14 +178,14 @@ static boolean isBridgeMethodFor(Method bridgeMethod, Method candidateMethod, Cl * are equal after resolving all types against the declaringType, otherwise * returns {@code false}. */ - private static boolean isResolvedTypeMatch(Method genericMethod, Method candidateMethod, Class targetClass) { + private static boolean isResolvedTypeMatch(Method genericMethod, Method candidateMethod, Class declaringClass) { Type[] genericParameters = genericMethod.getGenericParameterTypes(); if (genericParameters.length != candidateMethod.getParameterCount()) { return false; } Class[] candidateParameters = candidateMethod.getParameterTypes(); for (int i = 0; i < candidateParameters.length; i++) { - ResolvableType genericParameter = ResolvableType.forMethodParameter(genericMethod, i, targetClass); + ResolvableType genericParameter = ResolvableType.forMethodParameter(genericMethod, i, declaringClass); Class candidateParameter = candidateParameters[i]; if (candidateParameter.isArray()) { // An array type: compare the component type. diff --git a/spring-core/src/test/java/org/springframework/core/BridgeMethodResolverTests.java b/spring-core/src/test/java/org/springframework/core/BridgeMethodResolverTests.java index c6fb5dc4444e..b2bfb433296d 100644 --- a/spring-core/src/test/java/org/springframework/core/BridgeMethodResolverTests.java +++ b/spring-core/src/test/java/org/springframework/core/BridgeMethodResolverTests.java @@ -105,6 +105,17 @@ void findBridgedMethodFromOriginalMethodNotInHierarchy() throws Exception { assertThat(mostSpecificMethod).isSameAs(originalMethod); } + @Test + void findBridgedMethodInHierarchyWithBoundedGenerics() throws Exception { + Method originalMethod = Bar.class.getDeclaredMethod("someMethod", Object.class, Object.class); + assertThat(originalMethod.isBridge()).isFalse(); + Method bridgedMethod = BridgeMethodResolver.getMostSpecificMethod(originalMethod, SubBar.class); + assertThat(bridgedMethod.isBridge()).isFalse(); + assertThat(bridgedMethod.getName()).isEqualTo("someMethod"); + assertThat(bridgedMethod.getParameterCount()).isEqualTo(2); + assertThat(bridgedMethod.getParameterTypes()[0]).isEqualTo(CharSequence.class); + } + @Test void isBridgeMethodFor() throws Exception { Method bridged = MyBar.class.getDeclaredMethod("someMethod", String.class, Object.class); @@ -377,8 +388,15 @@ void someMethod(T theArg, Map m) { } - public abstract static class InterBar extends Bar { + public abstract static class InterBar extends Bar { + + @Override + void someMethod(T theArg, Object otherArg) { + } + } + + public abstract static class SubBar extends InterBar { }