methodutils.java
来自「这是一个有关common beanutils 的源码」· Java 代码 · 共 1,358 行 · 第 1/4 页
JAVA
1,358 行
*
* @param clazz get method from this class
* @param methodName get method with this name
* @param parameterType taking this type of parameter
* @return The accessible method
*/
public static Method getAccessibleMethod(
Class clazz,
String methodName,
Class parameterType) {
Class[] parameterTypes = {parameterType};
return getAccessibleMethod(clazz, methodName, parameterTypes);
}
/**
* <p>Return an accessible method (that is, one that can be invoked via
* reflection) with given name and parameters. If no such method
* can be found, return <code>null</code>.
* This is just a convenient wrapper for
* {@link #getAccessibleMethod(Method method)}.</p>
*
* @param clazz get method from this class
* @param methodName get method with this name
* @param parameterTypes with these parameters types
* @return The accessible method
*/
public static Method getAccessibleMethod(
Class clazz,
String methodName,
Class[] parameterTypes) {
try {
MethodDescriptor md = new MethodDescriptor(clazz, methodName, parameterTypes, true);
// Check the cache first
Method method = getCachedMethod(md);
if (method != null) {
return method;
}
method = getAccessibleMethod
(clazz, clazz.getMethod(methodName, parameterTypes));
cacheMethod(md, method);
return method;
} catch (NoSuchMethodException e) {
return (null);
}
}
/**
* <p>Return an accessible method (that is, one that can be invoked via
* reflection) that implements the specified Method. If no such method
* can be found, return <code>null</code>.</p>
*
* @param method The method that we wish to call
* @return The accessible method
*/
public static Method getAccessibleMethod(Method method) {
// Make sure we have a method to check
if (method == null) {
return (null);
}
return getAccessibleMethod(method.getDeclaringClass(), method);
}
/**
* <p>Return an accessible method (that is, one that can be invoked via
* reflection) that implements the specified Method. If no such method
* can be found, return <code>null</code>.</p>
*
* @param clazz The class of the object
* @param method The method that we wish to call
* @return The accessible method
*/
public static Method getAccessibleMethod(Class clazz, Method method) {
// Make sure we have a method to check
if (method == null) {
return (null);
}
// If the requested method is not public we cannot call it
if (!Modifier.isPublic(method.getModifiers())) {
return (null);
}
boolean sameClass = true;
if (clazz == null) {
clazz = method.getDeclaringClass();
} else {
sameClass = clazz.equals(method.getDeclaringClass());
if (!method.getDeclaringClass().isAssignableFrom(clazz)) {
throw new IllegalArgumentException(clazz.getName() +
" is not assignable from " + method.getDeclaringClass().getName());
}
}
// If the class is public, we are done
if (Modifier.isPublic(clazz.getModifiers())) {
if (!sameClass && !Modifier.isPublic(method.getDeclaringClass().getModifiers())) {
setMethodAccessible(method); // Default access superclass workaround
}
return (method);
}
String methodName = method.getName();
Class[] parameterTypes = method.getParameterTypes();
// Check the implemented interfaces and subinterfaces
method =
getAccessibleMethodFromInterfaceNest(clazz,
methodName,
parameterTypes);
// Check the superclass chain
if (method == null) {
method = getAccessibleMethodFromSuperclass(clazz,
methodName,
parameterTypes);
}
return (method);
}
// -------------------------------------------------------- Private Methods
/**
* <p>Return an accessible method (that is, one that can be invoked via
* reflection) by scanning through the superclasses. If no such method
* can be found, return <code>null</code>.</p>
*
* @param clazz Class to be checked
* @param methodName Method name of the method we wish to call
* @param parameterTypes The parameter type signatures
*/
private static Method getAccessibleMethodFromSuperclass
(Class clazz, String methodName, Class[] parameterTypes) {
Class parentClazz = clazz.getSuperclass();
while (parentClazz != null) {
if (Modifier.isPublic(parentClazz.getModifiers())) {
try {
return parentClazz.getMethod(methodName, parameterTypes);
} catch (NoSuchMethodException e) {
return null;
}
}
parentClazz = parentClazz.getSuperclass();
}
return null;
}
/**
* <p>Return an accessible method (that is, one that can be invoked via
* reflection) that implements the specified method, by scanning through
* all implemented interfaces and subinterfaces. If no such method
* can be found, return <code>null</code>.</p>
*
* <p> There isn't any good reason why this method must be private.
* It is because there doesn't seem any reason why other classes should
* call this rather than the higher level methods.</p>
*
* @param clazz Parent class for the interfaces to be checked
* @param methodName Method name of the method we wish to call
* @param parameterTypes The parameter type signatures
*/
private static Method getAccessibleMethodFromInterfaceNest
(Class clazz, String methodName, Class[] parameterTypes) {
Method method = null;
// Search up the superclass chain
for (; clazz != null; clazz = clazz.getSuperclass()) {
// Check the implemented interfaces of the parent class
Class[] interfaces = clazz.getInterfaces();
for (int i = 0; i < interfaces.length; i++) {
// Is this interface public?
if (!Modifier.isPublic(interfaces[i].getModifiers())) {
continue;
}
// Does the method exist on this interface?
try {
method = interfaces[i].getDeclaredMethod(methodName,
parameterTypes);
} catch (NoSuchMethodException e) {
/* Swallow, if no method is found after the loop then this
* method returns null.
*/
}
if (method != null) {
return method;
}
// Recursively check our parent interfaces
method =
getAccessibleMethodFromInterfaceNest(interfaces[i],
methodName,
parameterTypes);
if (method != null) {
return method;
}
}
}
// If we found a method return it
if (method != null) {
return (method);
}
// We did not find anything
return (null);
}
/**
* <p>Find an accessible method that matches the given name and has compatible parameters.
* Compatible parameters mean that every method parameter is assignable from
* the given parameters.
* In other words, it finds a method with the given name
* that will take the parameters given.<p>
*
* <p>This method is slightly undeterminstic since it loops
* through methods names and return the first matching method.</p>
*
* <p>This method is used by
* {@link
* #invokeMethod(Object object,String methodName,Object [] args,Class[] parameterTypes)}.
*
* <p>This method can match primitive parameter by passing in wrapper classes.
* For example, a <code>Boolean</code> will match a primitive <code>boolean</code>
* parameter.
*
* @param clazz find method in this class
* @param methodName find method with this name
* @param parameterTypes find method with compatible parameters
* @return The accessible method
*/
public static Method getMatchingAccessibleMethod(
Class clazz,
String methodName,
Class[] parameterTypes) {
// trace logging
Log log = LogFactory.getLog(MethodUtils.class);
if (log.isTraceEnabled()) {
log.trace("Matching name=" + methodName + " on " + clazz);
}
MethodDescriptor md = new MethodDescriptor(clazz, methodName, parameterTypes, false);
// see if we can find the method directly
// most of the time this works and it's much faster
try {
// Check the cache first
Method method = getCachedMethod(md);
if (method != null) {
return method;
}
method = clazz.getMethod(methodName, parameterTypes);
if (log.isTraceEnabled()) {
log.trace("Found straight match: " + method);
log.trace("isPublic:" + Modifier.isPublic(method.getModifiers()));
}
setMethodAccessible(method); // Default access superclass workaround
cacheMethod(md, method);
return method;
} catch (NoSuchMethodException e) { /* SWALLOW */ }
// search through all methods
int paramSize = parameterTypes.length;
Method bestMatch = null;
Method[] methods = clazz.getMethods();
float bestMatchCost = Float.MAX_VALUE;
float myCost = Float.MAX_VALUE;
for (int i = 0, size = methods.length; i < size ; i++) {
if (methods[i].getName().equals(methodName)) {
// log some trace information
if (log.isTraceEnabled()) {
log.trace("Found matching name:");
log.trace(methods[i]);
}
// compare parameters
Class[] methodsParams = methods[i].getParameterTypes();
int methodParamSize = methodsParams.length;
if (methodParamSize == paramSize) {
boolean match = true;
for (int n = 0 ; n < methodParamSize; n++) {
if (log.isTraceEnabled()) {
log.trace("Param=" + parameterTypes[n].getName());
log.trace("Method=" + methodsParams[n].getName());
}
if (!isAssignmentCompatible(methodsParams[n], parameterTypes[n])) {
if (log.isTraceEnabled()) {
log.trace(methodsParams[n] + " is not assignable from "
+ parameterTypes[n]);
}
match = false;
break;
}
}
if (match) {
// get accessible version of method
Method method = getAccessibleMethod(clazz, methods[i]);
if (method != null) {
if (log.isTraceEnabled()) {
log.trace(method + " accessible version of "
+ methods[i]);
}
setMethodAccessible(method); // Default access superclass workaround
myCost = getTotalTransformationCost(parameterTypes,method.getParameterTypes());
if ( myCost < bestMatchCost ) {
bestMatch = method;
bestMatchCost = myCost;
}
}
log.trace("Couldn't find accessible method.");
}
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?