package org.simpleframework.util;
import lombok.extern.slf4j.Slf4j;
import java.io.File;
import java.io.FileFilter;
import java.net.URL;
import java.util.HashSet;
import java.util.Set;
/**
* @author chongfayi
* @date 2021-10-21
*/
@Slf4j
public class ClassUtil {
public static final String FILE = "file";
/**
* 获取包下类集合
*
* @param packageName
* @return 类集合
*/
public static Set<Class<?>> extractPackClass(String packageName) {
//1.获取到类的加载器
ClassLoader classLoader = getClassLoader();
//2.通过类加载器获取到加载的资源
URL url = classLoader.getResource(packageName.replace(".", "/"));
if (url == null) {
log.warn("unable to retrieve anything from package" + packageName);
}
//3.根据不同的资源类型,采用不同的方式获取资源的集合
Set<Class<?>> classSet = null;
//过滤出文件类型的资源
if (FILE.equalsIgnoreCase(url.getProtocol())) {
classSet = new HashSet<Class<?>>();
File packageDirectory = new File(url.getPath());
extractClassFile(classSet, packageDirectory, packageName);
}
return classSet;
}
/**
* 递归获取目标package里面的所有class文件(包括子package里面的class文件)
*
* @param emptyClassSet 装载目标类的集合
* @param fileSource 文件获取目录
* @param packageName 包名
*/
private static void extractClassFile(final Set<Class<?>> emptyClassSet, File fileSource, final String packageName) {
if (!fileSource.isDirectory()) {
return;
}
//如果是一个文件夹,则调用其listFiles方法获取文件夹下的文件或文件夹
File[] files = fileSource.listFiles(new FileFilter() {
@Override
public boolean accept(File file) {
if (file.isDirectory()) {
return true;
} else {
//获取文件的绝对值路径
String absoluteFilePath = file.getAbsolutePath();
if (absoluteFilePath.endsWith(".class")) {
//class文件,直接加载
addToClassSet(absoluteFilePath);
}
}
return false;
}
//根据class文件的绝对值路径,获取并生成class对象,并放入classSet中
private void addToClassSet(String absoluteFilePath) {
//1.从class文件的绝对值路径里提取出包含了package的类名
absoluteFilePath = absoluteFilePath.replace(File.separator, ".");
String className = absoluteFilePath.substring(absoluteFilePath.indexOf(packageName));
className = className.substring(0, className.lastIndexOf("."));
//2.通过反射机制获取对应的Class对象并加入到classSet里
Class<?> targetClass = loadClass(className);
emptyClassSet.add(targetClass);
}
});
if (files != null) {
for (File f : files) {
extractClassFile(emptyClassSet, f, packageName);
}
}
}
/**
* 获取Class对象
*
* @param className class全名 = package + 类名
* @return Class
*/
public static Class<?> loadClass(String className) {
try {
return Class.forName(className);
} catch (ClassNotFoundException e) {
log.error("load class error", e);
throw new RuntimeException(e);
}
}
/**
* 获取ClassLoader
*
* @return 当前ClassLoader
*/
public static ClassLoader getClassLoader() {
return Thread.currentThread().getContextClassLoader();
}
}
单元测试:
package org.simple;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.simpleframework.util.ClassUtil;
import java.util.Set;
public class ClassUtilTest {
@DisplayName("提取目标类方法:extractPackageClassTest")
@Test
public void extractPackageClassTest(){
Set<Class<?>> classSet = ClassUtil.extractPackClass("com.imooc.entity");
System.out.println(classSet);
Assertions.assertEquals(4,classSet.size());
输出结果:
[class com.imooc.entity.bo.ShopCategory, class com.imooc.entity.dto.Result, class com.imooc.entity.dto.MainPageInfoDTO, class com.imooc.entity.bo.HeadLine]