首页

通过apache的commons-lang的MethodUtils工具类对java.lang.reflect.Method常用的操作功能增强

标签:MethodUtils,commons-lang,apache,方法工具类,reflect反射     发布时间:2018-02-10   

一、前言

关于apachecommons-lang开源包中基于org.apache.commons.lang3.reflect.MethodUtils方法工具类对java.lang.reflect.Method功能进行增强,主要方法调用invokeMethod、静态方法调用invokeExactStaticMethod、获取可访问方法getAccessibleMethod及获取重新覆盖的方法类集getOverrideHierarchy。

二、源码说明

源码中org.apache.commons.lang3.ArrayUtilsorg.apache.commons.lang3.ClassUtilsorg.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@}