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 6b03c7c33669..44390ec2dfd1 100644 --- a/spring-core/src/main/java/org/springframework/util/ClassUtils.java +++ b/spring-core/src/main/java/org/springframework/util/ClassUtils.java @@ -111,6 +111,11 @@ public abstract class ClassUtils { */ private static final Set> javaLanguageInterfaces; + /** + * Cache for equivalent methods on an interface implemented by the declaring class. + */ + private static final Map interfaceMethodCache = new ConcurrentReferenceHashMap<>(256); + static { primitiveWrapperTypeMap.put(Boolean.class, boolean.class); @@ -1277,13 +1282,16 @@ public static Method getMostSpecificMethod(Method method, @Nullable Class tar * @see #getMostSpecificMethod */ public static Method getInterfaceMethodIfPossible(Method method) { - if (Modifier.isPublic(method.getModifiers()) && !method.getDeclaringClass().isInterface()) { - Class current = method.getDeclaringClass(); + if (!Modifier.isPublic(method.getModifiers()) || method.getDeclaringClass().isInterface()) { + return method; + } + return interfaceMethodCache.computeIfAbsent(method, key -> { + Class current = key.getDeclaringClass(); while (current != null && current != Object.class) { Class[] ifcs = current.getInterfaces(); for (Class ifc : ifcs) { try { - return ifc.getMethod(method.getName(), method.getParameterTypes()); + return ifc.getMethod(key.getName(), key.getParameterTypes()); } catch (NoSuchMethodException ex) { // ignore @@ -1291,8 +1299,8 @@ public static Method getInterfaceMethodIfPossible(Method method) { } current = current.getSuperclass(); } - } - return method; + return key; + }); } /**