#1.什么是包扫描?
说到包扫描我们先要说一说包,包就是所谓的命名空间,用来区分哪些名字相同的类。
比如:我们知道ArrayList是一个系统类,我们在一个项目下建立一个包,比如叫做com.mec.core,在这个包下建立一个自己的类,类名也为ArrayList,系统会根据包名的不同,知道这是两个类。
这也充分的证明了为什么反射机制得到的类名是包名称 + 类名称。
我们建立好的包在文件夹中的状态是这样的
(比如包名叫做com.mec.core)
从上面的图中可以看出包名的每一个’ . ‘就是代表一个’ / ',代表该目录的下一级。
也就是说报扫描就是扫描一个目录,要扫描当前目录还要扫描子目录,一直到该目录的最底层。
#2.实现包扫描
package com.mec.ScannerPackage.core;
import java.io.File;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public abstract class PackageScanner {
public abstract void dealClass(Class<?> klass);
public PackageScanner() {
}
//这个方法用于处理一个文件
private void dealClassFile(String rootPackage, File file) {
String fileName = file.getName();//得到一个文件的名字
if (fileName.endsWith(".class")) {//如果这个文件的后缀名是.class
fileName = fileName.replace(".class", "");//去掉后缀名
try {
//包名+类名,加载这个类
Class<?> klass = Class.forName(rootPackage + "." + fileName);
dealClass(klass);
/*这是15行定义的抽象方法,我们工具只负责扫描到这个类
* 具体对于这个类的操作还是要交给是使用该工具的人
* 所以这里用了一个抽象方法
*/
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
//这个方法用于处理一个目录,因为目录下可能还有目录,所以要用到递归
private void dealDirectory(String rootPackage, File file) {
File[] files = file.listFiles();//通过该目录名得到该目录下的所有的文件和子目录
for (File filee : files) {//遍历这些目录
if (filee.isDirectory()) {//如果这个类是目录,我们就接着解析目录,递归
dealDirectory(rootPackage + "." + filee.getName() , filee);
}else if (filee.isFile()) {//如果这是一个文件
dealClassFile(rootPackage , filee);//处理它得到类的类类型
}
}
}
public void packageScanner(String packageName) {
String rootPackage = packageName;//保存包名
packageName = packageName.replace('.', '/');//把包名换成相应的路径名
URL url = Thread.currentThread().getContextClassLoader().getResource(packageName);
//通过路径名得到统一资源定位符
try {
URI uri = url.toURI();//通过URL的到统一资源标识符
File root = new File(uri);//通过URI得到该包的根目录。
dealDirectory(rootPackage, root);
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
}
#3.使用包扫描
假设扫描这个包:
package com.mec.ScannerPackage.test;
import com.mec.ScannerPackage.core.PackageScanner;
public class Test {
public static void main(String[] args) {
PackageScanner scanner = new PackageScanner() {
@Override
public void dealClass(Class<?> klass) {
System.out.println(klass.getName());
}
};
scanner.packageScanner("com.mec.Complex.core");
}
}
运行结果为: