|
|
|
@ -1466,10 +1466,8 @@ public abstract class ClassUtils { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Get the first publicly accessible method in the supplied method's type hierarchy that |
|
|
|
* Get the highest publicly accessible method in the supplied method's type hierarchy that |
|
|
|
* has a method signature equivalent to the supplied method, if possible. |
|
|
|
* has a method signature equivalent to the supplied method, if possible. |
|
|
|
* <p>If the supplied method is {@code public} and declared in a {@code public} type, |
|
|
|
|
|
|
|
* the supplied method will be returned. |
|
|
|
|
|
|
|
* <p>Otherwise, this method recursively searches the class hierarchy and implemented |
|
|
|
* <p>Otherwise, this method recursively searches the class hierarchy and implemented |
|
|
|
* interfaces for an equivalent method that is {@code public} and declared in a |
|
|
|
* interfaces for an equivalent method that is {@code public} and declared in a |
|
|
|
* {@code public} type. |
|
|
|
* {@code public} type. |
|
|
|
@ -1492,19 +1490,23 @@ public abstract class ClassUtils { |
|
|
|
* @see #getMostSpecificMethod(Method, Class) |
|
|
|
* @see #getMostSpecificMethod(Method, Class) |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public static Method getPubliclyAccessibleMethodIfPossible(Method method, @Nullable Class<?> targetClass) { |
|
|
|
public static Method getPubliclyAccessibleMethodIfPossible(Method method, @Nullable Class<?> targetClass) { |
|
|
|
Class<?> declaringClass = method.getDeclaringClass(); |
|
|
|
// If the method is not public, we can abort the search immediately.
|
|
|
|
// If the method is not public, we can abort the search immediately; or if the method's
|
|
|
|
if (!Modifier.isPublic(method.getModifiers())) { |
|
|
|
// declaring class is public, the method is already publicly accessible.
|
|
|
|
|
|
|
|
if (!Modifier.isPublic(method.getModifiers()) || Modifier.isPublic(declaringClass.getModifiers())) { |
|
|
|
|
|
|
|
return method; |
|
|
|
return method; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Method interfaceMethod = getInterfaceMethodIfPossible(method, targetClass, true); |
|
|
|
Method interfaceMethod = getInterfaceMethodIfPossible(method, targetClass, true); |
|
|
|
// If we found a method in a public interface, return the interface method.
|
|
|
|
// If we found a method in a public interface, return the interface method.
|
|
|
|
if (!interfaceMethod.equals(method)) { |
|
|
|
if (interfaceMethod != method) { |
|
|
|
return interfaceMethod; |
|
|
|
return interfaceMethod; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Class<?> declaringClass = method.getDeclaringClass(); |
|
|
|
|
|
|
|
// Bypass cache for java.lang.Object unless it is actually an overridable method declared there.
|
|
|
|
|
|
|
|
if (declaringClass.getSuperclass() == Object.class && !ReflectionUtils.isObjectMethod(method)) { |
|
|
|
|
|
|
|
return method; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Method result = publiclyAccessibleMethodCache.computeIfAbsent(method, |
|
|
|
Method result = publiclyAccessibleMethodCache.computeIfAbsent(method, |
|
|
|
key -> findPubliclyAccessibleMethodIfPossible(key.getName(), key.getParameterTypes(), declaringClass)); |
|
|
|
key -> findPubliclyAccessibleMethodIfPossible(key.getName(), key.getParameterTypes(), declaringClass)); |
|
|
|
return (result != null ? result : method); |
|
|
|
return (result != null ? result : method); |
|
|
|
@ -1513,19 +1515,19 @@ public abstract class ClassUtils { |
|
|
|
private static @Nullable Method findPubliclyAccessibleMethodIfPossible( |
|
|
|
private static @Nullable Method findPubliclyAccessibleMethodIfPossible( |
|
|
|
String methodName, Class<?>[] parameterTypes, Class<?> declaringClass) { |
|
|
|
String methodName, Class<?>[] parameterTypes, Class<?> declaringClass) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Method result = null; |
|
|
|
Class<?> current = declaringClass.getSuperclass(); |
|
|
|
Class<?> current = declaringClass.getSuperclass(); |
|
|
|
while (current != null) { |
|
|
|
while (current != null) { |
|
|
|
if (Modifier.isPublic(current.getModifiers())) { |
|
|
|
Method method = getMethodOrNull(current, methodName, parameterTypes); |
|
|
|
try { |
|
|
|
if (method == null) { |
|
|
|
return current.getDeclaredMethod(methodName, parameterTypes); |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
catch (NoSuchMethodException ex) { |
|
|
|
|
|
|
|
// ignore
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (Modifier.isPublic(method.getDeclaringClass().getModifiers())) { |
|
|
|
|
|
|
|
result = method; |
|
|
|
} |
|
|
|
} |
|
|
|
current = current.getSuperclass(); |
|
|
|
current = method.getDeclaringClass().getSuperclass(); |
|
|
|
} |
|
|
|
} |
|
|
|
return null; |
|
|
|
return result; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
|