包扫描----java
我要写一个包扫描工具,该工具实现从指定目录往下遍历,最终找到以.class文件结尾的类,将该类的元类对象以抽象方法参数的形式传给用户。
步骤: 1. 根据指定目录找出绝对路径,根据Protocol(协议)将目录分为jar目录和普通目录;
SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。2. 分别处理jar目录和普通目录。
3. 处理至找到了以.class文件结尾的类,将这个类的元类对象以抽象方法参数的形式传给用户。
直接贴代码:
package com.mec.util; import java.io.File; import java.net.JarURLConnection; import java.net.URL; import java.util.Enumeration; import java.util.jar.JarEntry; import java.util.jar.JarFile; public abstract class PackageScanner { public PackageScanner() { } public void scannerPackage(String packageName) { String packagePath = packageName.replace('.', '/'); //Eclipse下父目录与子目录以.相隔 //真正的路径中是以‘/’或‘\’相隔,此路径以‘\’相隔
ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); try { Enumeration<URL> resources = classLoader.getResources(packagePath); //得到绝对路径
while (resources.hasMoreElements()) { URL url = resources.nextElement(); if (url.getProtocol().equals("jar")) { //通过Protocol(协议)可以区分开jar文件和普通文件
scannerJar(url); // 将处理jar文件的代码单独写成一个内部方法,避免代码量过大
} else { File root = new File(url.toURI()); //将url转化成uri,以此创建File对象,后面解析就变成了对File的处理
scannerDirectory(root, packageName); // 同理将处理普通文件的代码单独也写成一个内部方法
} } } catch ( Exception e) { e.printStackTrace(); } } private void scannerDirectory(File currentFile, String packageName) { if (!currentFile.isDirectory()) { return; } File[] files = currentFile.listFiles(); // 得到File对象类型的【完整路径】的数组
for (File file : files) { if (file.isFile() && file.getName().endsWith(".class")) { String fileName = file.getName().replace(".class", ""); //去除掉后缀 .class
String className = packageName + "." + fileName; // 得到带包名的类,为取得元类对象做准备
try { Class<?> klass = Class.forName(className); dealClass(klass); //将得到的元类对象通过抽象方法参数传递给用户,以便用户后续操作。
} catch (ClassNotFoundException e) { e.printStackTrace(); } } else if (file.isDirectory()) { scannerDirectory(file, packageName + "." + file.getName()); // 此处采用递归,只要是目录就继续往下一层遍历,直到file.isFile()为true,且以.class结尾
} } } private void scannerJar(URL url) { try { JarURLConnection urlConnection = (JarURLConnection) url.openConnection(); JarFile jarFile = urlConnection.getJarFile(); // 取得jar文件的引用
Enumeration<JarEntry> jarEntries = jarFile.entries(); //JarFile 的 entries 方法返回一个所有条目的 Enumeration 对象
while (jarEntries.hasMoreElements()) { JarEntry jarEntry = jarEntries.nextElement(); //开始遍历,每个个体都是一个 JarEntry, 存在getName()方法
String name = jarEntry.getName(); if (jarEntry.isDirectory() || !name.endsWith(".class")) { continue; } name = name.replace(".class", ""); //去除掉后缀 .class
String className = name.replace('/', '.'); Class<?> klass = Class.forName(className); dealClass(klass); //将得到的元类对象通过抽象方法参数传递给用户,以便用户后续操作。
} } catch (Exception e) { e.printStackTrace(); } } public abstract void dealClass(Class<?> klass); }
经测试,上述代码可以完成包扫描过程。如果有些地方看不懂,可以上网查一查 。初学者学到这时,不应被 " 巫师的咒语 "吓倒,因为工具复杂,而不愿接受。相反,应站在工具本身发挥的作用角度来思考。积累的多了,见识的广了,才有资格去参悟那些 “ 巫师的咒语 ”。
更多精彩