java实现一个扫描包的工具类实例代码
程序员文章站
2024-02-23 14:32:40
前言
在很多的实际场景中,我们需要得到某个包名下面所有的类,比如我们在使用springmvc的时候,知道springmvc可以扫描指定包下的所有类,在平时的开发中,我们也...
前言
在很多的实际场景中,我们需要得到某个包名下面所有的类,比如我们在使用springmvc的时候,知道springmvc可以扫描指定包下的所有类,在平时的开发中,我们也有这样的场景,所以今天写一个扫描包的工具类,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。
代码如下:
package com.gujin.utils; import java.io.file; import java.io.filefilter; import java.io.ioexception; import java.net.jarurlconnection; import java.net.url; import java.net.urldecoder; import java.util.arraylist; import java.util.enumeration; import java.util.list; import java.util.jar.jarentry; import java.util.jar.jarfile; public class hqscanpackage { /** 是否循环迭代 **/ boolean recursive = true; /** 包名集合 **/ private list<string> packagenames = new arraylist<string>(); /** 过滤器 **/ private hqscanpackagefilter filter = null; /** 监听器 **/ private hqscanpackagelistener listener = null; /** * 是否循环迭代 * * @return */ public boolean isrecursive() { return recursive; } /** * 设置是否循环迭代 * * @param recursive */ public void setrecursive(boolean recursive) { this.recursive = recursive; } /** * 获得过滤器 * * @return */ public hqscanpackagefilter getfilter() { return filter; } /** * 设置过滤器 * * @param filter */ public void setfilter(hqscanpackagefilter filter) { this.filter = filter; } /** * 获得监听器 * * @return */ public hqscanpackagelistener getlistener() { return listener; } /** * 设置监听器 * * @param listener */ public void setlistener(hqscanpackagelistener listener) { this.listener = listener; } /** * 添加扫描包 * * @param packagename */ public void addpackage(string packagename) { if (packagename == null || !packagename.matches("[\\w]+(\\.[\\w]+)*")) { throw new illegalargumentexception("非法包名."); } this.packagenames.add(packagename); } /** * 清空扫描包 */ public void clearpackage() { this.packagenames.clear(); } /** * 扫描 */ public void scan() { for (string packagename : packagenames) { scan(packagename); } } /** * 是否接受 * * @param clazz * @return */ private boolean accept(class<?> clazz) { if (this.filter != null) { return this.filter.accept(clazz); } return true; } /** * 触发扫描到合法类 * * @param clazz * @return */ private void trrigeronscanclass(class<?> clazz) { if (this.listener != null) { this.listener.onscanclass(clazz); } } /** * 扫描到类 * * @param clazz * @return */ private void onscanclass(class<?> clazz) { if (accept(clazz)) { trrigeronscanclass(clazz); } } /** * 从包package中获取所有的class * * @param packagename * @return */ private void scan(string packagename) { // 获取包的名字 并进行替换 string packagedirname = packagename.replace('.', '/'); // 定义一个枚举的集合 并进行循环来处理这个目录下的things enumeration<url> dirs = null; try { dirs = thread.currentthread().getcontextclassloader() .getresources(packagedirname); // 循环迭代下去 while (dirs.hasmoreelements()) { // 获取下一个元素 url url = dirs.nextelement(); // 得到协议的名称 string protocol = url.getprotocol(); // 如果是以文件的形式保存在服务器上 if ("file".equals(protocol)) { // 获取包的物理路径 string filepath = urldecoder.decode(url.getfile(), "utf-8"); // 以文件的方式扫描整个包下的文件 并添加到集合中 findandaddclassesinpackagebyfile(packagename, filepath); } else if ("jar".equals(protocol)) { // 如果是jar包文件 // 定义一个jarfile jarfile jar = null; try { // 获取jar jar = ((jarurlconnection) url.openconnection()).getjarfile(); // 从此jar包 得到一个枚举类 enumeration<jarentry> 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 // 使用class.forname会触发类静态方法 class<?> clazz = thread.currentthread() .getcontextclassloader().loadclass( packagename + '.' + classname); onscanclass(clazz); } catch (classnotfoundexception e) { system.err.println("加载类出错"); } } } } } } catch (ioexception e) { system.err.println("在扫描用户定义视图时从jar包获取文件出错"); e.printstacktrace(); } } } } catch (ioexception e) { system.err.println("扫描出错"); e.printstacktrace(); } } /** * 以文件的形式来获取包下的所有class * * @param packagename * @param packagepath */ private void findandaddclassesinpackagebyfile(string packagename, string packagepath) { // 获取此包的目录 建立一个file file dir = new file(packagepath); // 如果不存在或者 也不是目录就直接返回 if (!dir.exists() || !dir.isdirectory()) { system.err.println("用户定义包名 " + 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()); } else { // 如果是java类文件 去掉后面的.class 只留下类名 string classname = file.getname().substring(0, file.getname().length() - 6); try { class<?> clazz = thread.currentthread().getcontextclassloader() .loadclass(packagename + '.' + classname); onscanclass(clazz); } catch (classnotfoundexception e) { system.err.println("添加用户自定义视图类错误 找不到此类的.class文件"); e.printstacktrace(); } } } } /** * 扫描包过滤器 * * @author jianggujin * */ public static interface hqscanpackagefilter { /** * 是否接受 * * @param clazz * @return */ public boolean accept(class<?> clazz); } /** * 扫描包监听 * * @author jianggujin * */ public static interface hqscanpackagelistener { /** * 扫描到合法类执行 * * @param clazz */ public void onscanclass(class<?> clazz); } public static void main(string[] args) { hqscanpackage scanpackage = new hqscanpackage(); scanpackage.addpackage(hqscanpackage.class.getpackage().getname()); scanpackage.setfilter(new hqscanpackagefilter() { @override public boolean accept(class<?> clazz) { return true; } }); scanpackage.setlistener(new hqscanpackagelistener() { @override public void onscanclass(class<?> clazz) { system.out.println(clazz); } }); scanpackage.scan(); } }
运行可以得到如下结果:
class com.gujin.utils.hqscanpackage$1 class com.gujin.utils.hqscanpackage$2 class com.gujin.utils.hqscanpackage$3 interface com.gujin.utils.hqscanpackage$hqscanpackagefilter interface com.gujin.utils.hqscanpackage$hqscanpackagelistener class com.gujin.utils.hqscanpackage
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。