public PackageScanner() {
}
//扫描包
private void scanFile(File currentFile, String packageName) {
//File[] fileList = file.listFiles();
//得到该文件夹下的所有 类+子文件夹的名称
//此处list应为扫描包下的所有类的nameList,所以不应该有文件名称
//所以应该加一个文件过滤器
File[] fileList = currentFile.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
if(pathname.isDirectory()) {
return true;
}
return pathname.getName().endsWith(".class");
}
});
for(File f : fileList) {
//如果是文件夹,递归处理
if(f.isDirectory()) {
scanFile(f, packageName + "." + f.getName());
} else {
String className = packageName + "."
+ f.getName().replace(".class", "");
try {
Class<?> klass = Class.forName(className);//得到类
//可以筛选类
if(klass.isAnnotation()//是注解
|| klass.isEnum()//是枚举
|| klass.isInterface()//是接口
|| klass.isPrimitive()) {//是基本类型
continue;
//这些类型我们不需要 所以不处理
}
dealClass(klass);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
//扫描jar包
private void scanJarPackage(URL url) throws IOException {
//连接jar文件的一个入口连接定位
JarURLConnection urlConnection = (JarURLConnection) url.openConnection();
JarFile jarFile = urlConnection.getJarFile();//得到jar文件
Enumeration<JarEntry> jarEntries = jarFile.entries();
//读取jar文件下的内容
while(jarEntries.hasMoreElements()) {
JarEntry jarEntry = jarEntries.nextElement();
String jarName = jarEntry.getName();
if (jarEntry.isDirectory() || !jarName.endsWith(".class")) {
continue;
}
String className = jarName.replace(".class", "").replaceAll("/", ".");
try {
Class<?> klass = Class.forName(className);
if (klass.isAnnotation()
|| klass.isInterface()
|| klass.isEnum()
|| klass.isPrimitive()) {
continue;
}
dealClass(klass);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
public void packageScanner(String packageName) {
String packageRelativePath = packageName.replace('.', '/');
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
//线程.得到当前线程.得到类加载器(当前线程即这个test,但不能直接用test. ,
//因为java是多线程的,可能不会得到这个test)
try {
Enumeration<URL> resource
= classLoader.getResources(packageRelativePath);
//一个枚举类型集合
while(resource.hasMoreElements()) {
URL url = resource.nextElement();
if(url.getProtocol().equals("jar")) {
scanJarPackage(url);
} else {
File file = new File(url.toURI());
if(!file.exists()) {//file不存在
continue;
}
//得到要扫描的包(即文件夹) 此处为classes
scanFile(file, packageName);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public abstract void dealClass(Class<?> klass);
public static void main(String[] args) {
String packageName = "com.zty.classes";
//path如果是以 / 开头,就从classpath中去找
//(classpath是bin目录或是target的classes目录)
//如果不以/开头,就以当前类的位置开始找
new PackageScanner(){
@Override
public void dealClass(Class<?> klass) {
System.out.println(klass.getName());
}
}.packageScanner(packageName);
}
扫描的包为:
运行结果:
剔除了枚举、接口、注解及基本类型之后的结果。