From edcf1a0562475ffc603cbe31de032a3e21d80732 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 30 Jun 2020 09:18:32 +0200 Subject: [PATCH] =?UTF-8?q?DATACMNS-1108=20-=20Prefer=20regular=20methods?= =?UTF-8?q?=20in=20ReflectionUtils.findRequiredMethod(=E2=80=A6).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit findRequiredMethod(…) now prefers regular methods over synthetic/bridge methods. This refinement is required for newer Java versions that create synthetic bridge methods using the interface's return type. For SpEL extension introspection we're looking for the most specific return type that may be declared in the extension. Original Pull Request: #454 --- .../data/util/ReflectionUtils.java | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/springframework/data/util/ReflectionUtils.java b/src/main/java/org/springframework/data/util/ReflectionUtils.java index 417908e15..63b60d16d 100644 --- a/src/main/java/org/springframework/data/util/ReflectionUtils.java +++ b/src/main/java/org/springframework/data/util/ReflectionUtils.java @@ -247,17 +247,34 @@ public final class ReflectionUtils { } /** - * Returns the method with the given name of the given class and parameter types. + * Returns the method with the given name of the given class and parameter types. Prefers regular methods over + * {@link Method#isBridge() bridge} and {@link Method#isSynthetic() synthetic} ones. * * @param type must not be {@literal null}. * @param name must not be {@literal null}. * @param parameterTypes must not be {@literal null}. - * @return + * @return the method object. * @throws IllegalArgumentException in case the method cannot be resolved. */ public static Method findRequiredMethod(Class type, String name, Class... parameterTypes) { - Method result = org.springframework.util.ReflectionUtils.findMethod(type, name, parameterTypes); + Assert.notNull(type, "Class must not be null"); + Assert.notNull(name, "Method name must not be null"); + + Method result = null; + Class searchType = type; + while (searchType != null) { + Method[] methods = (searchType.isInterface() ? searchType.getMethods() + : org.springframework.util.ReflectionUtils.getDeclaredMethods(searchType)); + for (Method method : methods) { + if (name.equals(method.getName()) && hasSameParams(method, parameterTypes)) { + if (result == null || result.isSynthetic() || result.isBridge()) { + result = method; + } + } + } + searchType = searchType.getSuperclass(); + } if (result == null) { @@ -272,6 +289,10 @@ public final class ReflectionUtils { return result; } + private static boolean hasSameParams(Method method, Class[] paramTypes) { + return (paramTypes.length == method.getParameterCount() && Arrays.equals(paramTypes, method.getParameterTypes())); + } + /** * Returns a {@link Stream} of the return and parameters types of the given {@link Method}. *