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 f8bbfbf78fb9..172bfbea9208 100644 --- a/spring-core/src/main/java/org/springframework/core/BridgeMethodResolver.java +++ b/spring-core/src/main/java/org/springframework/core/BridgeMethodResolver.java @@ -46,6 +46,7 @@ * @author Rob Harrop * @author Juergen Hoeller * @author Phillip Webb + * @author Yanming Zhou * @since 2.0 */ public final class BridgeMethodResolver { @@ -86,6 +87,9 @@ public static Method findBridgedMethod(Method bridgeMethod) { * @see org.springframework.util.ClassUtils#getMostSpecificMethod */ public static Method getMostSpecificMethod(Method bridgeMethod, @Nullable Class targetClass) { + if (targetClass != null && !bridgeMethod.getDeclaringClass().isAssignableFrom(targetClass)) { + return bridgeMethod; + } Method specificMethod = ClassUtils.getMostSpecificMethod(bridgeMethod, targetClass); return resolveBridgeMethod(specificMethod, (targetClass != null ? targetClass : specificMethod.getDeclaringClass())); diff --git a/spring-core/src/main/java/org/springframework/util/ClassUtils.java b/spring-core/src/main/java/org/springframework/util/ClassUtils.java index 77fa719717ea..b6c2e0f31735 100644 --- a/spring-core/src/main/java/org/springframework/util/ClassUtils.java +++ b/spring-core/src/main/java/org/springframework/util/ClassUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2023 the original author or authors. + * Copyright 2002-2024 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. @@ -64,6 +64,7 @@ * @author Rob Harrop * @author Sam Brannen * @author Sebastien Deleuze + * @author Yanming Zhou * @since 1.1 * @see TypeUtils * @see ReflectionUtils @@ -1455,6 +1456,9 @@ private static boolean isGroovyObjectMethod(Method method) { * @param targetClass the target class to check against */ private static boolean isOverridable(Method method, @Nullable Class targetClass) { + if (targetClass != null && !method.getDeclaringClass().isAssignableFrom(targetClass)) { + return false; + } if ((method.getModifiers() & NON_OVERRIDABLE_MODIFIER) != 0) { return false; } 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 449d886d920c..63eac578cf58 100644 --- a/spring-core/src/test/java/org/springframework/core/BridgeMethodResolverTests.java +++ b/spring-core/src/test/java/org/springframework/core/BridgeMethodResolverTests.java @@ -38,6 +38,7 @@ * @author Rob Harrop * @author Juergen Hoeller * @author Chris Beams + * @author Yanming Zhou */ @SuppressWarnings("rawtypes") class BridgeMethodResolverTests { @@ -97,6 +98,13 @@ void findBridgedMethodFromOriginalMethodInHierarchy() throws Exception { assertThat(bridgedMethod.getParameterTypes()[0]).isEqualTo(Date.class); } + @Test + void findBridgedMethodFromOriginalMethodNotInHierarchy() throws Exception { + Method originalMethod = Adder.class.getMethod("add", Object.class); + Method mostSpecificMethod = BridgeMethodResolver.getMostSpecificMethod(originalMethod, FakeAdder.class); + assertThat(mostSpecificMethod).isSameAs(originalMethod); + } + @Test void isBridgeMethodFor() throws Exception { Method bridged = MyBar.class.getDeclaredMethod("someMethod", String.class, Object.class); @@ -405,6 +413,11 @@ public void add(Date date) { } } + public static class FakeAdder { + + public void add(Date date) { + } + } public static class Enclosing { diff --git a/spring-core/src/test/java/org/springframework/util/ClassUtilsTests.java b/spring-core/src/test/java/org/springframework/util/ClassUtilsTests.java index 7d93be159859..df2ed6845247 100644 --- a/spring-core/src/test/java/org/springframework/util/ClassUtilsTests.java +++ b/spring-core/src/test/java/org/springframework/util/ClassUtilsTests.java @@ -55,6 +55,7 @@ * @author Rob Harrop * @author Rick Evans * @author Sam Brannen + * @author Yanming Zhou */ class ClassUtilsTests { @@ -408,6 +409,8 @@ void getMostSpecificMethod() throws NoSuchMethodException { .isEqualTo(ClassUtils.getMethod(MethodsInterfaceImplementation.class, "print", String.class)); assertThat(ClassUtils.getMostSpecificMethod(printMethod, SubMethodsInterfaceImplementation.class)) .isEqualTo(ClassUtils.getMethod(MethodsInterfaceImplementation.class, "print", String.class)); + assertThat(ClassUtils.getMostSpecificMethod(printMethod, FakeMethodsInterface.class)) + .isSameAs(printMethod); Method protectedPrintMethod = MethodsInterfaceImplementation.class.getDeclaredMethod("protectedPrint"); assertThat(ClassUtils.getMostSpecificMethod(protectedPrintMethod, MethodsInterfaceImplementation.class)) @@ -631,4 +634,10 @@ public void packageAccessiblePrint() { } + private class FakeMethodsInterface { + + public void print(String message) { + + } + } }