/**
  * Attempt to find a {@link Method} on the supplied class with the supplied name and parameter
  * types. Searches all superclasses up to {@code Object}.
  *
  * <p>Returns {@code null} if no {@link Method} can be found.
  *
  * @param clazz the class to introspect
  * @param name the name of the method
  * @param paramTypes the parameter types of the method (may be {@code null} to indicate any
  *     signature)
  * @return the Method object, or {@code null} if none found
  */
 public static Method findMethod(Class<?> clazz, String name, Class<?>... paramTypes) {
   Assert.notNull(clazz, "Class must not be null");
   Assert.notNull(name, "Method name must not be null");
   Class<?> searchType = clazz;
   while (searchType != null) {
     Method[] methods =
         (searchType.isInterface() ? searchType.getMethods() : getDeclaredMethods(searchType));
     for (Method method : methods) {
       if (name.equals(method.getName())
           && (paramTypes == null || Arrays.equals(paramTypes, method.getParameterTypes()))) {
         return method;
       }
     }
     searchType = searchType.getSuperclass();
   }
   return null;
 }
 /**
  * Determine whether the given method explicitly declares the given exception or one of its
  * superclasses, which means that an exception of that type can be propagated as-is within a
  * reflective invocation.
  *
  * @param method the declaring method
  * @param exceptionType the exception to throw
  * @return {@code true} if the exception can be thrown as-is; {@code false} if it needs to be
  *     wrapped
  */
 public static boolean declaresException(Method method, Class<?> exceptionType) {
   Assert.notNull(method, "Method must not be null");
   Class<?>[] declaredExceptions = method.getExceptionTypes();
   for (Class<?> declaredException : declaredExceptions) {
     if (declaredException.isAssignableFrom(exceptionType)) {
       return true;
     }
   }
   return false;
 }
 /** 循环向上转型,获取类的DeclaredField. */
 @SuppressWarnings("unchecked")
 protected static Field getDeclaredField(final Class clazz, final String fieldName) {
   Assert.notNull(clazz, "clazz不能为空");
   Assert.hasText(fieldName, "fieldName");
   for (Class superClass = clazz;
       superClass != Object.class;
       superClass = superClass.getSuperclass()) {
     try {
       return superClass.getDeclaredField(fieldName);
     } catch (NoSuchFieldException e) {
       // Field不在当前类定义,继续向上转型
     }
   }
   return null;
 }
 /**
  * Attempt to find a {@link Field field} on the supplied {@link Class} with the supplied {@code
  * name} and/or {@link Class type}. Searches all superclasses up to {@link Object}.
  *
  * @param clazz the class to introspect
  * @param name the name of the field (may be {@code null} if type is specified)
  * @param type the type of the field (may be {@code null} if name is specified)
  * @return the corresponding Field object, or {@code null} if not found
  */
 public static Field findField(Class<?> clazz, String name, Class<?> type) {
   Assert.notNull(clazz, "Class must not be null");
   Assert.isTrue(
       name != null || type != null, "Either name or type of the field must be specified");
   Class<?> searchType = clazz;
   while (!Object.class.equals(searchType) && searchType != null) {
     Field[] fields = searchType.getDeclaredFields();
     for (Field field : fields) {
       if ((name == null || name.equals(field.getName()))
           && (type == null || type.equals(field.getType()))) {
         return field;
       }
     }
     searchType = searchType.getSuperclass();
   }
   return null;
 }
 /** 循环向上转型,获取对象的DeclaredField. */
 protected static Field getDeclaredField(final Object object, final String fieldName) {
   Assert.notNull(object, "object不能为空");
   return getDeclaredField(object.getClass(), fieldName);
 }