ConcurrentReferenceHashMap cache for getInterfaceMethodIfPossible results

Closes gh-24206
This commit is contained in:
Juergen Hoeller
2019-12-16 16:49:39 +01:00
parent 634aba4ab6
commit afe22b84c2

View File

@@ -110,6 +110,11 @@ public abstract class ClassUtils {
*/ */
private static final Set<Class<?>> javaLanguageInterfaces; private static final Set<Class<?>> javaLanguageInterfaces;
/**
* Cache for equivalent methods on an interface implemented by the declaring class.
*/
private static final Map<Method, Method> interfaceMethodCache = new ConcurrentReferenceHashMap<>(256);
static { static {
primitiveWrapperTypeMap.put(Boolean.class, boolean.class); primitiveWrapperTypeMap.put(Boolean.class, boolean.class);
@@ -1291,13 +1296,16 @@ public abstract class ClassUtils {
* @see #getMostSpecificMethod * @see #getMostSpecificMethod
*/ */
public static Method getInterfaceMethodIfPossible(Method method) { public static Method getInterfaceMethodIfPossible(Method method) {
if (Modifier.isPublic(method.getModifiers()) && !method.getDeclaringClass().isInterface()) { if (!Modifier.isPublic(method.getModifiers()) || method.getDeclaringClass().isInterface()) {
Class<?> current = method.getDeclaringClass(); return method;
}
return interfaceMethodCache.computeIfAbsent(method, key -> {
Class<?> current = key.getDeclaringClass();
while (current != null && current != Object.class) { while (current != null && current != Object.class) {
Class<?>[] ifcs = current.getInterfaces(); Class<?>[] ifcs = current.getInterfaces();
for (Class<?> ifc : ifcs) { for (Class<?> ifc : ifcs) {
try { try {
return ifc.getMethod(method.getName(), method.getParameterTypes()); return ifc.getMethod(key.getName(), key.getParameterTypes());
} }
catch (NoSuchMethodException ex) { catch (NoSuchMethodException ex) {
// ignore // ignore
@@ -1305,8 +1313,8 @@ public abstract class ClassUtils {
} }
current = current.getSuperclass(); current = current.getSuperclass();
} }
} return key;
return method; });
} }
/** /**