【小工具】包扫描器 ——PackageScanner
需求 分析:
凡是主流框架,大多都提供了 许多注解
而这些注解被使用后,是如何被程序察觉到的呢?
只有扫描到指定包内的类之后,才能根据这个类的信息,
来判断是否进行后续的操作
那么,这就需要本篇博文的主题 —— 包扫描器 来解决!
本人来展示下代码:
实现 代码:
package edu.youzg.util;
import java.io.File;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
/**
* 包扫描器<br/>
* scanPackage() —— 扫描指定的包<br/>
* dealClass() —— 处理扫描到的 类的Class对象
*
* @author Youzg
*/
public abstract class PackageScanner {
public PackageScanner() {
}
/**
* 处理类
* @param klass 扫描到的类的Class对象
*/
public abstract void dealClass(Class<?> klass);
/**
* 通过 所传File类参数 以及 相应的包名称 来 处理包
* @param cur 当前扫描到的File
* @param packageName 目标包名称
*/
private void dealPackage(File cur, String packageName) {
File[] files = cur.listFiles();
for (File file : files) { // 遍历这个问渐渐中的所有包含的子文件/子文件夹
if (file.isFile()) { // 如果是文件
String fileName = file.getName();
if (!fileName.endsWith(".class")) { // 如果是.class文件
continue;
}
fileName = fileName.replace(".class", "");
String className = packageName + "." + fileName;
try {
Class<?> klass = Class.forName(className);
dealClass(klass);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} else { // 如果是文件夹
dealPackage(file, packageName + "." + file.getName());
}
}
}
/**
* 通过URL来处理相应的Jar包
* @param url 目标URL
*/
private void dealJar(URL url) {
try {
JarURLConnection connection = (JarURLConnection) url.openConnection();
JarFile jarFile = connection.getJarFile();
Enumeration<JarEntry> entryList = jarFile.entries();
while (entryList.hasMoreElements()) {
JarEntry jarEntry = entryList.nextElement();
if (jarEntry.isDirectory() || !jarEntry.getName().endsWith(".class")) { // 如果是文件夹,或者不是.class文件,运行下一轮循环
continue;
}
String className = jarEntry.getName(); // 组装我们执行反射机制所需的类名
className = className.replace(".class", "");
className = className.replace('/', '.');
try {
Class<?> klass = Class.forName(className);
dealClass(klass); // 处理通过反射机制所获得的类
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 通过 所给的包名称,去扫描 这个包中的所有信息
*
* @param packageName 指定的包名
*/
public void scanPackage(String packageName) {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
String pathName = packageName.replace('.', '/');
try {
Enumeration<URL> urls = classLoader.getResources(pathName);
while (urls.hasMoreElements()) { // 如果包含很多文件(即:不是文件夹就是Jar包)
URL url = urls.nextElement();
if (url.getProtocol().equals("jar")) { // 如果是Jar包
dealJar(url);
} else { // 如果是文件夹
try {
File curFile = new File(url.toURI());
dealPackage(curFile, packageName);
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
相信看了 很多框架源码的同学 会了解到 本类的重要性的!
那么,在本人《Java 高级技术》专栏中,也极大程度上利用了这个小工具,欢迎 有兴趣的同学 前往观看!