一、前言
关于apache的commons-lang开源包中基于org.apache.commons.lang3.reflect.MethodUtils方法工具类对java.lang.reflect.Method功能进行增强,主要方法调用invokeMethod、静态方法调用invokeExactStaticMethod、获取可访问方法getAccessibleMethod及获取重新覆盖的方法类集getOverrideHierarchy。
二、源码说明
源码中org.apache.commons.lang3.ArrayUtils、org.apache.commons.lang3.ClassUtils、org.apache.commons.lang3.Validate分别参加其他更多文章
package org.apache.commons.lang3.reflect;@b@@b@import java.lang.reflect.InvocationTargetException;@b@import java.lang.reflect.Method;@b@import java.lang.reflect.Modifier;@b@import java.lang.reflect.Type;@b@import java.util.Arrays;@b@import java.util.Iterator;@b@import java.util.LinkedHashSet;@b@import java.util.Map;@b@import java.util.Set;@b@import org.apache.commons.lang3.ArrayUtils;@b@import org.apache.commons.lang3.ClassUtils;@b@import org.apache.commons.lang3.ClassUtils.Interfaces;@b@import org.apache.commons.lang3.Validate;@b@@b@public class MethodUtils@b@{@b@ public static Object invokeMethod(Object object, String methodName, Object[] args)@b@ throws NoSuchMethodException, IllegalAccessException, InvocationTargetException@b@ {@b@ args = ArrayUtils.nullToEmpty(args);@b@ Class[] parameterTypes = ClassUtils.toClass(args);@b@ return invokeMethod(object, methodName, args, parameterTypes);@b@ }@b@@b@ public static Object invokeMethod(Object object, String methodName, Object[] args, Class<?>[] parameterTypes)@b@ throws NoSuchMethodException, IllegalAccessException, InvocationTargetException@b@ {@b@ parameterTypes = ArrayUtils.nullToEmpty(parameterTypes);@b@ args = ArrayUtils.nullToEmpty(args);@b@ Method method = getMatchingAccessibleMethod(object.getClass(), methodName, parameterTypes);@b@@b@ if (method == null) {@b@ throw new NoSuchMethodException("No such accessible method: " + methodName + "() on object: " + object.getClass().getName());@b@ }@b@@b@ return method.invoke(object, args);@b@ }@b@@b@ public static Object invokeExactMethod(Object object, String methodName, Object[] args)@b@ throws NoSuchMethodException, IllegalAccessException, InvocationTargetException@b@ {@b@ args = ArrayUtils.nullToEmpty(args);@b@ Class[] parameterTypes = ClassUtils.toClass(args);@b@ return invokeExactMethod(object, methodName, args, parameterTypes);@b@ }@b@@b@ public static Object invokeExactMethod(Object object, String methodName, Object[] args, Class<?>[] parameterTypes)@b@ throws NoSuchMethodException, IllegalAccessException, InvocationTargetException@b@ {@b@ args = ArrayUtils.nullToEmpty(args);@b@ parameterTypes = ArrayUtils.nullToEmpty(parameterTypes);@b@ Method method = getAccessibleMethod(object.getClass(), methodName, parameterTypes);@b@@b@ if (method == null) {@b@ throw new NoSuchMethodException("No such accessible method: " + methodName + "() on object: " + object.getClass().getName());@b@ }@b@@b@ return method.invoke(object, args);@b@ }@b@@b@ public static Object invokeExactStaticMethod(Class<?> cls, String methodName, Object[] args, Class<?>[] parameterTypes)@b@ throws NoSuchMethodException, IllegalAccessException, InvocationTargetException@b@ {@b@ args = ArrayUtils.nullToEmpty(args);@b@ parameterTypes = ArrayUtils.nullToEmpty(parameterTypes);@b@ Method method = getAccessibleMethod(cls, methodName, parameterTypes);@b@ if (method == null) {@b@ throw new NoSuchMethodException("No such accessible method: " + methodName + "() on class: " + cls.getName());@b@ }@b@@b@ return method.invoke(null, args);@b@ }@b@@b@ public static Object invokeStaticMethod(Class<?> cls, String methodName, Object[] args)@b@ throws NoSuchMethodException, IllegalAccessException, InvocationTargetException@b@ {@b@ args = ArrayUtils.nullToEmpty(args);@b@ Class[] parameterTypes = ClassUtils.toClass(args);@b@ return invokeStaticMethod(cls, methodName, args, parameterTypes);@b@ }@b@@b@ public static Object invokeStaticMethod(Class<?> cls, String methodName, Object[] args, Class<?>[] parameterTypes)@b@ throws NoSuchMethodException, IllegalAccessException, InvocationTargetException@b@ {@b@ args = ArrayUtils.nullToEmpty(args);@b@ parameterTypes = ArrayUtils.nullToEmpty(parameterTypes);@b@ Method method = getMatchingAccessibleMethod(cls, methodName, parameterTypes);@b@@b@ if (method == null) {@b@ throw new NoSuchMethodException("No such accessible method: " + methodName + "() on class: " + cls.getName());@b@ }@b@@b@ return method.invoke(null, args);@b@ }@b@@b@ public static Object invokeExactStaticMethod(Class<?> cls, String methodName, Object[] args)@b@ throws NoSuchMethodException, IllegalAccessException, InvocationTargetException@b@ {@b@ args = ArrayUtils.nullToEmpty(args);@b@ Class[] parameterTypes = ClassUtils.toClass(args);@b@ return invokeExactStaticMethod(cls, methodName, args, parameterTypes);@b@ }@b@@b@ public static Method getAccessibleMethod(Class<?> cls, String methodName, Class<?>[] parameterTypes)@b@ {@b@ try@b@ {@b@ return getAccessibleMethod(cls.getMethod(methodName, parameterTypes));@b@ } catch (NoSuchMethodException e) {@b@ }@b@ return null;@b@ }@b@@b@ public static Method getAccessibleMethod(Method method)@b@ {@b@ if (!(MemberUtils.isAccessible(method))) {@b@ return null;@b@ }@b@@b@ Class cls = method.getDeclaringClass();@b@ if (Modifier.isPublic(cls.getModifiers()))@b@ return method;@b@@b@ String methodName = method.getName();@b@ Class[] parameterTypes = method.getParameterTypes();@b@@b@ method = getAccessibleMethodFromInterfaceNest(cls, methodName, parameterTypes);@b@@b@ if (method == null) {@b@ method = getAccessibleMethodFromSuperclass(cls, methodName, parameterTypes);@b@ }@b@@b@ return method;@b@ }@b@@b@ private static Method getAccessibleMethodFromSuperclass(Class<?> cls, String methodName, Class<?>[] parameterTypes)@b@ {@b@ Class parentClass = cls.getSuperclass();@b@ while (parentClass != null) {@b@ if (Modifier.isPublic(parentClass.getModifiers()))@b@ try {@b@ return parentClass.getMethod(methodName, parameterTypes);@b@ } catch (NoSuchMethodException e) {@b@ return null;@b@ }@b@@b@ parentClass = parentClass.getSuperclass();@b@ }@b@ return null;@b@ }@b@@b@ private static Method getAccessibleMethodFromInterfaceNest(Class<?> cls, String methodName, Class<?>[] parameterTypes)@b@ {@b@ if (cls != null)@b@ {@b@ Class[] interfaces = cls.getInterfaces();@b@ int i = 0; if (i < interfaces.length)@b@ {@b@ if (!(Modifier.isPublic(interfaces[i].getModifiers())));@b@ }@b@@b@ try@b@ {@b@ return interfaces[i].getDeclaredMethod(methodName, parameterTypes);@b@ }@b@ catch (NoSuchMethodException method)@b@ {@b@ while (true)@b@ {@b@ Method method = getAccessibleMethodFromInterfaceNest(interfaces[i], methodName, parameterTypes);@b@@b@ if (method != null)@b@ return method;@b@ ++i;@b@ }@b@ cls = cls.getSuperclass();@b@ }@b@@b@ }@b@@b@ return null;@b@ }@b@@b@ public static Method getMatchingAccessibleMethod(Class<?> cls, String methodName, Class<?>[] parameterTypes)@b@ {@b@ Method method;@b@ Method bestMatch;@b@ try@b@ {@b@ method = cls.getMethod(methodName, parameterTypes);@b@ MemberUtils.setAccessibleWorkaround(method);@b@ return method;@b@ }@b@ catch (NoSuchMethodException bestMatch)@b@ {@b@ bestMatch = null;@b@ Method[] methods = cls.getMethods();@b@ Method[] arr$ = methods; int len$ = arr$.length; for (int i$ = 0; i$ < len$; ++i$) { Method method = arr$[i$];@b@@b@ if ((method.getName().equals(methodName)) && (ClassUtils.isAssignable(parameterTypes, method.getParameterTypes(), true)))@b@ {@b@ Method accessibleMethod = getAccessibleMethod(method);@b@ if ((accessibleMethod != null) && (((bestMatch == null) || (MemberUtils.compareParameterTypes(accessibleMethod.getParameterTypes(), bestMatch.getParameterTypes(), parameterTypes) < 0))))@b@ {@b@ bestMatch = accessibleMethod;@b@ }@b@ }@b@ }@b@ if (bestMatch != null)@b@ MemberUtils.setAccessibleWorkaround(bestMatch);@b@ }@b@ return bestMatch;@b@ }@b@@b@ public static Set<Method> getOverrideHierarchy(Method method, ClassUtils.Interfaces interfacesBehavior)@b@ {@b@ Validate.notNull(method);@b@ Set result = new LinkedHashSet();@b@ result.add(method);@b@@b@ Class[] parameterTypes = method.getParameterTypes();@b@@b@ Class declaringClass = method.getDeclaringClass();@b@@b@ Iterator hierarchy = ClassUtils.hierarchy(declaringClass, interfacesBehavior).iterator();@b@@b@ hierarchy.next();@b@ while (true) { Method m;@b@ while (true) { while (true) { if (!(hierarchy.hasNext())) break label201;@b@ Class c = (Class)hierarchy.next();@b@ m = getMatchingAccessibleMethod(c, method.getName(), parameterTypes);@b@ if (m != null)@b@ break;@b@ }@b@ if (!(Arrays.equals(m.getParameterTypes(), parameterTypes)))@b@ break;@b@ result.add(m);@b@ }@b@@b@ Map typeArguments = TypeUtils.getTypeArguments(declaringClass, m.getDeclaringClass());@b@ int i = 0;@b@ while (true) { while (true) { if (i >= parameterTypes.length) break label189;@b@ Type childType = TypeUtils.unrollVariables(typeArguments, method.getGenericParameterTypes()[i]);@b@ Type parentType = TypeUtils.unrollVariables(typeArguments, m.getGenericParameterTypes()[i]);@b@ if (TypeUtils.equals(childType, parentType))@b@ break;@b@ }@b@ ++i;@b@ }@b@@b@ label189: result.add(m);@b@ }@b@ label201: return result;@b@ }@b@}