【Java工具】包扫描工具

包扫描

  这个工具是在学了注解和反射机制后,遇到要把Model包下的所有有相关注解的类进行操作的时候遇到的。手动一个个Class.forName(className)太麻烦了,并且还要进行相应的筛选。因此才想出来做包扫描工具,把扫描过程用一个类完成,其他如何操作向外提供。

  我们知道一个工程下可能有许多的包或者Jar包,包扫描工具是为了结合注解可以准确的定位到一个需要的类上。并且扫描到一个包下的所有类方便我们使用反射机制。

  包扫描工具功能:给一个包名字,扫描该包下的所有类,如何操作这些类对外提供出去。

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;

public abstract class PackageScanner {

	public PackageScanner() {
	}
	
	public abstract void dealClass(Class<?> klass);
	
	private void dealPackage(File curFile, String packageName) {
		
		File[] files = curFile.listFiles();
		for (File file : files) {
			if (file.isFile()) {
				String fileName = file.getName();
				if (!fileName.endsWith(".class")) {
					continue;
				}
				fileName = fileName.replace(".class", "");
				String className = packageName + "." + fileName;
				try {
					Class<?> klass = Class.forName(className);
					dealClass(klass);
				} catch (ClassNotFoundException e) {
					e.printStackTrace();
				}
			}
			if (file.isDirectory()) {
				dealPackage(file, packageName + "." + file.getName());
			}
		}
	}
	
	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();
				String name = jarEntry.getName();
				if (jarEntry.isDirectory() || !name.endsWith(".class")) {
					continue;
				}
				name = name.replace(".class", "");
				String className = name.replace('/', '.');
				Class<?> klass = Class.forName(className);
				dealClass(klass);
			}
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	public void scanPackage(String packageName) {
		ClassLoader classLoader = Thread.currentThread().getContextClassLoader();// 得到当前类加载器
		String pathName = packageName.replace('.', '/'); //把包名称改为路径
		try {
			Enumeration<URL> urls = classLoader.getResources(pathName);
			while (urls.hasMoreElements()) {
				URL url = urls.nextElement();
				if (url.getProtocol().equals("jar")) {
					dealJar(url);
				} else {
					try {
						File curFile = new File(url.toURI());
						dealPackage(curFile, packageName);
					} catch (URISyntaxException e) {
						e.printStackTrace();
					}
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
	
}

使用方式

public class LocalTest {

	public static void main(String[] args) {

		new PackageScanner() {

			@Override
			public void dealClass(Class<?> klass) {
				if (klass.isPrimitive() || klass.isAnnotation() || klass.isInterface() || klass.isArray() || klass.isEnum()) {
					return;
				}
				System.out.println(klass.getName());
			}
		}.scanPackage("com.mec");
	}

}

  需要注意的是:扫描自己的jar包可能扫描不出类很有可能是这个问题。

解决方法:
在这里插入图片描述
记得导出我们自己的包时,要将Add directory entries这一项勾上,否则扫描不到。

关于这里的Thread.currentThread().getContextClassLoader();,线程的 contextClassLoader 是从父线程那里继承过来的,所谓父线程就是创建了当前线程的线程。程序启动时的 main 线程的 contextClassLoader 就是 AppClassLoader。这意味着如果没有人工去设置,那么所有的线程的 contextClassLoader 都是AppClassLoader。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值