zoukankan      html  css  js  c++  java
  • Java遍历包中所有类方法注解

      1 import java.io.File;
      2 import java.io.FileFilter;
      3 import java.io.IOException;
      4 import java.lang.annotation.Annotation;
      5 import java.lang.reflect.Method;
      6 import java.net.JarURLConnection;
      7 import java.net.URL;
      8 import java.net.URLDecoder;
      9 import java.util.Enumeration;
     10 import java.util.Iterator;
     11 import java.util.LinkedHashSet;
     12 import java.util.Set;
     13 import java.util.jar.JarEntry;
     14 import java.util.jar.JarFile;
     15 
     16 public class ClassUtil {
     17 
     18     public static void main(String[] args) {
     19         
     20         // 包下面的类
     21         Set<Class<?>> clazzs = getClasses("cn.package.test");
     22         if (clazzs == null) {
     23             return;
     24         }
     25 
     26         System.out.printf(clazzs.size() + "");
     27         // 某类或者接口的子类
     28         Set<Class<?>> inInterface = getByInterface(Object.class, clazzs);
     29         System.out.printf(inInterface.size() + "");
     30 
     31         for (Class<?> clazz : clazzs) {
     32 
     33             // 获取类上的注解
     34             Annotation[] annos = clazz.getAnnotations();
     35             for (Annotation anno : annos) {
     36                 System.out.println(clazz.getSimpleName().concat(".").concat(anno.annotationType().getSimpleName()));
     37             }
     38 
     39             // 获取方法上的注解
     40             Method[] methods = clazz.getDeclaredMethods();
     41             for (Method method : methods) {
     42                 Annotation[] annotations = method.getDeclaredAnnotations();
     43                 for (Annotation annotation : annotations) {
     44                     System.out.println(clazz.getSimpleName().concat(".").concat(method.getName()).concat(".")
     45                             .concat(annotation.annotationType().getSimpleName()));
     46                 }
     47             }
     48         }
     49 
     50     }
     51 
     52     /**
     53      * 从包package中获取所有的Class
     54      *
     55      * @param pack
     56      * @return
     57      */
     58     public static Set<Class<?>> getClasses(String pack) {
     59 
     60         // 第一个class类的集合
     61         Set<Class<?>> classes = new LinkedHashSet<>();
     62         // 是否循环迭代
     63         boolean recursive = true;
     64         // 获取包的名字 并进行替换
     65         String packageName = pack;
     66         String packageDirName = packageName.replace('.', '/');
     67         // 定义一个枚举的集合 并进行循环来处理这个目录下的things
     68         Enumeration<URL> dirs;
     69         try {
     70             dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
     71             // 循环迭代下去
     72             while (dirs.hasMoreElements()) {
     73                 // 获取下一个元素
     74                 URL url = dirs.nextElement();
     75                 // 得到协议的名称
     76                 String protocol = url.getProtocol();
     77                 // 如果是以文件的形式保存在服务器上
     78                 if ("file".equals(protocol)) {
     79                     System.err.println("file类型的扫描");
     80                     // 获取包的物理路径
     81                     String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
     82                     // 以文件的方式扫描整个包下的文件 并添加到集合中
     83                     findAndAddClassesInPackageByFile(packageName, filePath, recursive, classes);
     84                 } else if ("jar".equals(protocol)) {
     85                     // 如果是jar包文件
     86                     // 定义一个JarFile
     87                     // System.err.println("jar类型的扫描");
     88                     JarFile jar;
     89                     try {
     90                         // 获取jar
     91                         jar = ((JarURLConnection) url.openConnection()).getJarFile();
     92                         // 从此jar包 得到一个枚举类
     93                         Enumeration<JarEntry> entries = jar.entries();
     94                         // 同样的进行循环迭代
     95                         while (entries.hasMoreElements()) {
     96                             // 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文件
     97                             JarEntry entry = entries.nextElement();
     98                             String name = entry.getName();
     99                             // 如果是以/开头的
    100                             if (name.charAt(0) == '/') {
    101                                 // 获取后面的字符串
    102                                 name = name.substring(1);
    103                             }
    104                             // 如果前半部分和定义的包名相同
    105                             if (name.startsWith(packageDirName)) {
    106                                 int idx = name.lastIndexOf('/');
    107                                 // 如果以"/"结尾 是一个包
    108                                 if (idx != -1) {
    109                                     // 获取包名 把"/"替换成"."
    110                                     packageName = name.substring(0, idx).replace('/', '.');
    111                                 }
    112                                 // 如果可以迭代下去 并且是一个包
    113                                 if ((idx != -1) || recursive) {
    114                                     // 如果是一个.class文件 而且不是目录
    115                                     if (name.endsWith(".class") && !entry.isDirectory()) {
    116                                         // 去掉后面的".class" 获取真正的类名
    117                                         String className = name.substring(packageName.length() + 1, name.length() - 6);
    118                                         try {
    119                                             // 添加到classes
    120                                             classes.add(Class.forName(packageName + '.' + className));
    121                                         } catch (ClassNotFoundException e) {
    122                                             e.printStackTrace();
    123                                         }
    124                                     }
    125                                 }
    126                             }
    127                         }
    128                     } catch (IOException e) {
    129                         // log.error("在扫描用户定义视图时从jar包获取文件出错");
    130                         e.printStackTrace();
    131                     }
    132                 }
    133             }
    134         } catch (IOException e) {
    135             e.printStackTrace();
    136         }
    137 
    138         return classes;
    139     }
    140 
    141     /**
    142      * 以文件的形式来获取包下的所有Class
    143      *
    144      * @param packageName
    145      * @param packagePath
    146      * @param recursive
    147      * @param classes
    148      */
    149     public static void findAndAddClassesInPackageByFile(String packageName, String packagePath, final boolean recursive,
    150             Set<Class<?>> classes) {
    151         // 获取此包的目录 建立一个File
    152         File dir = new File(packagePath);
    153         // 如果不存在或者 也不是目录就直接返回
    154         if (!dir.exists() || !dir.isDirectory()) {
    155             // log.warn("用户定义包名 " + packageName + " 下没有任何文件");
    156             return;
    157         }
    158         // 如果存在 就获取包下的所有文件 包括目录
    159         File[] dirfiles = dir.listFiles(new FileFilter() {
    160             // 自定义过滤规则 如果可以循环(包含子目录) 或则是以.class结尾的文件(编译好的java类文件)
    161             public boolean accept(File file) {
    162                 return (recursive && file.isDirectory()) || (file.getName().endsWith(".class"));
    163             }
    164         });
    165         // 循环所有文件
    166         for (File file : dirfiles) {
    167             // 如果是目录 则继续扫描
    168             if (file.isDirectory()) {
    169                 findAndAddClassesInPackageByFile(packageName + "." + file.getName(), file.getAbsolutePath(), recursive,
    170                         classes);
    171             } else {
    172                 // 如果是java类文件 去掉后面的.class 只留下类名
    173                 String className = file.getName().substring(0, file.getName().length() - 6);
    174                 try {
    175                     // 添加到集合中去
    176                     // classes.add(Class.forName(packageName + '.' + className));
    177                     // 经过回复同学的提醒,这里用forName有一些不好,会触发static方法,没有使用classLoader的load干净
    178                     classes.add(
    179                             Thread.currentThread().getContextClassLoader().loadClass(packageName + '.' + className));
    180                 } catch (ClassNotFoundException e) {
    181                     // log.error("添加用户自定义视图类错误 找不到此类的.class文件");
    182                     e.printStackTrace();
    183                 }
    184             }
    185         }
    186     }
    187 
    188     // --------------------------------------------------------------------------------------------------------
    189 
    190     @SuppressWarnings({ "rawtypes", "unchecked" })
    191     public static Set<Class<?>> getByInterface(Class clazz, Set<Class<?>> classesAll) {
    192         Set<Class<?>> classes = new LinkedHashSet<Class<?>>();
    193         // 获取指定接口的实现类
    194         if (!clazz.isInterface()) {
    195             try {
    196                 /**
    197                  * 循环判断路径下的所有类是否继承了指定类 并且排除父类自己
    198                  */
    199                 Iterator<Class<?>> iterator = classesAll.iterator();
    200                 while (iterator.hasNext()) {
    201                     Class<?> cls = iterator.next();
    202                     /**
    203                      * isAssignableFrom该方法的解析,请参考博客:
    204                      * http://blog.csdn.net/u010156024/article/details/44875195
    205                      */
    206                     if (clazz.isAssignableFrom(cls)) {
    207                         if (!clazz.equals(cls)) {// 自身并不加进去
    208                             classes.add(cls);
    209                         } else {
    210 
    211                         }
    212                     }
    213                 }
    214             } catch (Exception e) {
    215                 System.out.println("出现异常");
    216             }
    217         }
    218         return classes;
    219     }
    220 
    221 }
  • 相关阅读:
    回调函数(C语言)
    main函数的参数(一)
    术语,概念
    [LeetCode] Invert Binary Tree
    关于overload和override
    第一个只出现一次的字符
    Manacher算法----最长回文子串
    C++对象模型
    回文判断
    字符串转换成整数
  • 原文地址:https://www.cnblogs.com/vianzhang/p/9350728.html
Copyright © 2011-2022 走看看