#1.什么是包扫描?
说到包扫描我们先要说一说包,包就是所谓的命名空间,用来区分哪些名字相同的类。
比如:我们知道ArrayList是一个系统类,我们在一个项目下建立一个包,比如叫做com.mec.core,在这个包下建立一个自己的类,类名也为ArrayList,系统会根据包名的不同,知道这是两个类。
这也充分的证明了为什么反射机制得到的类名是包名称 + 类名称。

我们建立好的包在文件夹中的状态是这样的

(比如包名叫做com.mec.core)

java 扫描确定目录中非文件夹的文件 java扫描包下的类_包扫描工具


java 扫描确定目录中非文件夹的文件 java扫描包下的类_包扫描_02


从上面的图中可以看出包名的每一个’ . ‘就是代表一个’ / ',代表该目录的下一级。

也就是说报扫描就是扫描一个目录,要扫描当前目录还要扫描子目录,一直到该目录的最底层。

#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.使用包扫描

假设扫描这个包:

java 扫描确定目录中非文件夹的文件 java扫描包下的类_包名_03

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");
	}
}

运行结果为:

java 扫描确定目录中非文件夹的文件 java扫描包下的类_包扫描_04