content: package com.lcw.util;
  
  import com.lcw.model.ParameterModel;
  import java.io.InputStream;
  import java.lang.reflect.Field;
  import java.lang.reflect.Method;
  import java.lang.reflect.ParameterizedType;
  import java.net.JarURLConnection;
  import java.net.URL;
  import java.net.URLClassLoader;
  import java.nio.file.attribute.FileTime;
  import java.util.ArrayList;
  import java.util.Collections;
  import java.util.Date;
  import java.util.Enumeration;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  import java.util.Set;
  import java.util.jar.JarEntry;
  import java.util.jar.JarFile;
  import org.apache.commons.lang.time.DateUtils;
  import org.objectweb.asm.ClassReader;
  import org.objectweb.asm.Type;
  import org.objectweb.asm.tree.ClassNode;
  import org.objectweb.asm.tree.LocalVariableNode;
  import org.objectweb.asm.tree.MethodNode;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  /**
   *
   * @author lancw
   */
  public class ReflectUtil {
  
      private static final Logger LOGGER = LoggerFactory.getLogger(ReflectUtil.class.getName());
      private static final HashMap<String, List<MethodNode>> CACHE = new HashMap<>();
  
      /**
       * 获取方法参数名称
       *
       * @param theMethod
       * @return
       * @throws Exception
       */
      public static List<ParameterModel> getParameterNames(Method theMethod) throws Exception {
          Class<?> declaringClass = theMethod.getDeclaringClass();
          String key = declaringClass.getName();
          String constructorDescriptor = Type.getMethodDescriptor(theMethod);
          if (CACHE.get(key) == null) {
              ClassLoader declaringClassLoader = declaringClass.getClassLoader();
  
              Type declaringType = Type.getType(declaringClass);
              String url = declaringType.getInternalName() + ".class";
  
              InputStream classFileInputStream = declaringClassLoader.getResourceAsStream(url);
              if (classFileInputStream == null) {
                  throw new IllegalArgumentException("The constructor's class loader cannot find the bytecode that defined the constructor's class (URL: " + url + ")");
              }
  
              ClassNode classNode;
              try {
                  classNode = new ClassNode();
                  ClassReader classReader = new ClassReader(classFileInputStream);
                  classReader.accept(classNode, 0);
              } finally {
                  classFileInputStream.close();
              }
              CACHE.put(key, classNode.methods);
          }
  
          List<MethodNode> methods = CACHE.get(key);
          for (MethodNode method : methods) {
              if (method.name.equals(theMethod.getName()) && method.desc.equals(constructorDescriptor)) {
                  Type[] argumentTypes = Type.getArgumentTypes(method.desc);
                  List<ParameterModel> parameterNames = new ArrayList<>(argumentTypes.length);
  
                  List<LocalVariableNode> localVariables = method.localVariables;
                  if (localVariables == null) {
                      for (int i = 0; i < argumentTypes.length; i++) {
                          Type at = argumentTypes[i];
                          String name = theMethod.getParameters()[i].getName();
                          parameterNames.add(new ParameterModel(name, at.toString(), theMethod, i));
                      }
                  } else {
                      Collections.sort(localVariables, (LocalVariableNode o1, LocalVariableNode o2) -> Integer.valueOf(o1.index).compareTo(o2.index));
                      for (int i = 1; i <= argumentTypes.length; i++) {
                          LocalVariableNode lvn = localVariables.get(i);
                          parameterNames.add(new ParameterModel(lvn.name, lvn.desc, theMethod, i - 1));
                      }
                  }
                  return parameterNames;
              }
          }
          return null;
      }
  
      /**
       * 从jar包中查找指定接口的一个实现类 非反射
       *
       * @param interfaceClass
       * @param jarPath
       * @return
       * @throws Exception
       */
      public static Class findImplementFromJar(Class interfaceClass, URL jarPath) throws Exception {
          URL url = new URL("jar:" + jarPath.toString() + "!/");
          JarURLConnection jarConnection = (JarURLConnection) url.openConnection();
          JarFile jarFile = jarConnection.getJarFile();
          Enumeration<JarEntry> je = jarFile.entries();
          boolean flag = false;
          while (je.hasMoreElements()) {
              JarEntry e = je.nextElement();
              String n = e.getName();
              FileTime ft = e.getLastModifiedTime();
              if (DateUtils.addDays(new Date(), -100).getTime() - ft.toMillis() > 0) {
                  LOGGER.info("jar文件时间超过100天，跳过查找实现类：" + jarFile.getName().substring(jarFile.getName().lastIndexOf("\\")) + ft.toString());
                  return null;
              } else {
                  if (!flag) {
                      flag = true;
                      LOGGER.info("在" + jarFile.getName().substring(jarFile.getName().lastIndexOf("\\")) + "中查找实现类");
                  }
              }
              if (n.endsWith(".class")) {
                  n = n.substring(0, n.length() - 6);
                  n = n.replace('/', '.');
                  Class currentClass = ClassLoader.getSystemClassLoader().loadClass(n);
                  if (interfaceClass.isAssignableFrom(currentClass) && !n.equals(interfaceClass.getName())) {
                      return currentClass;
                  }
              }
          }
          return null;
      }
  
      /**
       * 添加classPath
       *
       * @param url
       * @throws Exception
       */
      public static void addURL(URL url) throws Exception {
          Class[] parameters = new Class[]{URL.class};
          URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSystemClassLoader();
          Class sysclass = URLClassLoader.class;
          try {
              Method method = sysclass.getDeclaredMethod("addURL", parameters);
              method.setAccessible(true);
              method.invoke(sysloader, new Object[]{url});
          } catch (Throwable t) {
              LOGGER.error("Error, could not add URL to system classloader", t);
          }
      }
  
      /**
       * 获取泛型类型
       *
       * @param t
       * @param index
       * @return
       */
      public static Class getParameterizedTypes(java.lang.reflect.Type t, int index) {
          if (t instanceof ParameterizedType) {
              ParameterizedType pt = (ParameterizedType) t;
              Class genericClazz = (Class) pt.getActualTypeArguments()[index];
              return genericClazz;
          }
          return null;
      }
      private static final String[] NOT_ANALYSIS_CLASS = new String[]{"java.lang", "java.math", "java.sql.Date", "java.util.Date"};
  
      /**
       * 检查是否不需要解析的class类型
       *
       * @param c
       * @return
       */
      public static boolean isNotAnalysisClass(String c) {
          for (String s : NOT_ANALYSIS_CLASS) {
              if (c.contains(s)) {
                  return true;
              }
          }
          return false;
      }
  
      /**
       * 解析class的所有字段转为伪json
       *
       * @param c    要转换的class
       * @param deep 深度
       * @return
       */
      public static String classToJson(Class c, int deep) {
          StringBuilder sb = new StringBuilder();
          Field[] fs = c.getDeclaredFields();
          if (deep > 5 || isNotAnalysisClass(c.getName())) {
              return "";
          }
          sb.append("{");
          for (int i = 0; i < fs.length; i++) {
              Field f = fs[i];
              Class t = f.getType();
              if (t.isPrimitive() || t.isEnum() || isNotAnalysisClass(t.getTypeName())) {
                  sb.append(f.getName()).append(":''");
              } else if (t.isArray()) {
                  sb.append(f.getName()).append(":[]");
              } else if (t.isInterface()) {
                  if (t.isAssignableFrom(List.class) || t.isAssignableFrom(Set.class)) {
                      Class gc = ReflectUtil.getParameterizedTypes(f.getGenericType(), 0);
                      if (deep < 5) {
                          sb.append(f.getName()).append(":[").append(classToJson(gc, deep + 1)).append("]");
                      } else {
                          sb.append(f.getName()).append(":[").append(gc).append("]");
                      }
                  } else if (t.isAssignableFrom(Map.class)) {
                      Class gc = ReflectUtil.getParameterizedTypes(f.getGenericType(), 1);
                      if (deep < 3) {
                          sb.append(f.getName()).append(":{key:").append(classToJson(gc, deep + 1)).append("}");
                      } else {
                          sb.append(f.getName()).append(":{key:").append(gc).append("}");
                      }
                  } else {
                      sb.append(f.getName()).append(":").append(classToJson(t, deep + 1));
                  }
              } else {
                  sb.append(f.getName()).append(":").append(classToJson(t, deep + 1));
              }
              if (i != fs.length - 1) {
                  sb.append(",");
              }
          }
          sb.append("}");
          return sb.toString();
      }
  }
  