博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java读取指定package下的所有class
阅读量:6670 次
发布时间:2019-06-25

本文共 4298 字,大约阅读时间需要 14 分钟。

hot3.png

之前在看spring注解的时候,有看到再配置文件里面定义component scan package就能自动扫描对应包下面的class,

然后根据注解生成相应的bean。自己对这个功能很好奇,就搜了下,找到了实现的关键代码,记录下。后续再对这段代码深入学习。

/**  * 从包package中获取所有的Class  *   * @param pack  * @return  */ public static Set
> getClasses(String pack) {  // 第一个class类的集合  Set
> classes = new LinkedHashSet
>();  // 是否循环迭代  boolean recursive = true;  // 获取包的名字 并进行替换  String packageName = pack;  String packageDirName = packageName.replace('.', '/');  // 定义一个枚举的集合 并进行循环来处理这个目录下的things  Enumeration
 dirs;  try {   dirs = Thread.currentThread().getContextClassLoader().getResources(     packageDirName);   // 循环迭代下去   while (dirs.hasMoreElements()) {    // 获取下一个元素    URL url = dirs.nextElement();    // 得到协议的名称    String protocol = url.getProtocol();    // 如果是以文件的形式保存在服务器上    if ("file".equals(protocol)) {     System.err.println("file类型的扫描");     // 获取包的物理路径     String filePath = URLDecoder.decode(url.getFile(), "UTF-8");     // 以文件的方式扫描整个包下的文件 并添加到集合中     findAndAddClassesInPackageByFile(packageName, filePath,       recursive, classes);    } else if ("jar".equals(protocol)) {     // 如果是jar包文件     // 定义一个JarFile     System.err.println("jar类型的扫描");     JarFile jar;     try {      // 获取jar      jar = ((JarURLConnection) url.openConnection())        .getJarFile();      // 从此jar包 得到一个枚举类      Enumeration
 entries = jar.entries();      // 同样的进行循环迭代      while (entries.hasMoreElements()) {       // 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文件       JarEntry entry = entries.nextElement();       String name = entry.getName();       // 如果是以/开头的       if (name.charAt(0) == '/') {        // 获取后面的字符串        name = name.substring(1);       }       // 如果前半部分和定义的包名相同       if (name.startsWith(packageDirName)) {        int idx = name.lastIndexOf('/');        // 如果以"/"结尾 是一个包        if (idx != -1) {         // 获取包名 把"/"替换成"."         packageName = name.substring(0, idx)           .replace('/', '.');        }        // 如果可以迭代下去 并且是一个包        if ((idx != -1) || recursive) {         // 如果是一个.class文件 而且不是目录         if (name.endsWith(".class")           && !entry.isDirectory()) {          // 去掉后面的".class" 获取真正的类名          String className = name.substring(            packageName.length() + 1, name              .length() - 6);          try {           // 添加到classes           classes.add(Class             .forName(packageName + '.'               + className));          } catch (ClassNotFoundException e) {           // log           // .error("添加用户自定义视图类错误 找不到此类的.class文件");           e.printStackTrace();          }         }        }       }      }     } catch (IOException e) {      // log.error("在扫描用户定义视图时从jar包获取文件出错");      e.printStackTrace();     }    }   }  } catch (IOException e) {   e.printStackTrace();  }  return classes; }    /**  * 以文件的形式来获取包下的所有Class  *   * @param packageName  * @param packagePath  * @param recursive  * @param classes  */ public static void findAndAddClassesInPackageByFile(String packageName,   String packagePath, final boolean recursive, Set
> classes) {  // 获取此包的目录 建立一个File  File dir = new File(packagePath);  // 如果不存在或者 也不是目录就直接返回  if (!dir.exists() || !dir.isDirectory()) {   // log.warn("用户定义包名 " + packageName + " 下没有任何文件");   return;  }  // 如果存在 就获取包下的所有文件 包括目录  File[] dirfiles = dir.listFiles(new FileFilter() {   // 自定义过滤规则 如果可以循环(包含子目录) 或则是以.class结尾的文件(编译好的java类文件)   public boolean accept(File file) {    return (recursive && file.isDirectory())      || (file.getName().endsWith(".class"));   }  });  // 循环所有文件  for (File file : dirfiles) {   // 如果是目录 则继续扫描   if (file.isDirectory()) {    findAndAddClassesInPackageByFile(packageName + "."      + file.getName(), file.getAbsolutePath(), recursive,      classes);   } else {    // 如果是java类文件 去掉后面的.class 只留下类名    String className = file.getName().substring(0,      file.getName().length() - 6);    try {     // 添加到集合中去     //classes.add(Class.forName(packageName + '.' + className));                                         //经过回复同学的提醒,这里用forName有一些不好,会触发static方法,没有使用classLoader的load干净                                        classes.add(Thread.currentThread().getContextClassLoader().loadClass(packageName + '.' + className));                                  } catch (ClassNotFoundException e) {     // log.error("添加用户自定义视图类错误 找不到此类的.class文件");     e.printStackTrace();    }   }  } }

自己直接拿过来用了,可以扫描package对应的子package,不过是对当前classLoad下的所有jar进行扫描的。

转载于:https://my.oschina.net/artong999/blog/357310

你可能感兴趣的文章
5G 第五代移动通信系统你知多少?
查看>>
导致硬盘录像机卡死的十大原因分析
查看>>
大数据广告技术公司WindyVale获百万美元投资
查看>>
《Servlet和JSP学习指南》一2.3 cookie
查看>>
乘风破浪,抚州“智慧”之旅扬帆起航
查看>>
《Hadoop实战第2版》——1.6节Hadoop数据管理
查看>>
大型数据中心100GbE部署将大增
查看>>
专访田渊栋 | Torch升级版PyTorch开源,Python为先,强GPU加速
查看>>
别再鼓吹神通广大的黑客了 只有务实才能让高管和董事会加大网络安全投入
查看>>
Wi-Fi频谱的未来 有望突破传统频谱
查看>>
【首发】OpsWorld大会主题分享《抽丝剥茧之MySQL疑难杂症排查》
查看>>
《Lua游戏开发实践指南》一3.3本章小结
查看>>
《Android程序设计》一3.2 活动、意图和任务
查看>>
2016 机器学习之路:一年从无到有掌握机器学习
查看>>
红杉计越:AI、大数据、SaaS、云计算为何在中国一体迸发?
查看>>
阿里张勇:数据驱动的透明是平台治理的基础
查看>>
思科零售业解决方案助力企业提升服务与客户体验
查看>>
《哈利·波特》出版二十周年,教大家用神经网络写咒语!
查看>>
希捷发布全球首款2TB M.2 SSD固态硬盘
查看>>
《Java语言导学(原书第6版)》一一3.4 控制流语句
查看>>