“类图”(ClassGraph)
用于 JVM 语言的超快速、超轻量级类路径和模块扫描程序。
maven仓库配置
<!-- https://mvnrepository.com/artifact/io.github.classgraph/classgraph -->
<dependency>
<groupId>io.github.classgraph</groupId>
<artifactId>classgraph</artifactId>
<version>4.8.161</version>
</dependency>
扫描包的工具类
import io.github.classgraph.ClassGraph;
import io.github.classgraph.ScanResult;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.List;
/**
* 扫描工具类
* 该工具类提供扫描包的方法,用于获取包中的类信息。
*
* @author 安然的尾巴
* @version 1.0
*/
public class ScanUtil {
/**
* 扫描指定的包,并返回相关的Class对象
*
* @param packages 要扫描的包名
* @return 包中的类对象列表
*/
public static List<Class<?>> scan(String... packages) {
// 使用try-with-resources语句,这可以自动关闭在其内部打开的资源,以防止资源泄漏
try (ScanResult scan = new ClassGraph()
// enableAllInfo()方法启用所有扫描信息,包括类信息、方法信息、字段信息等等
.enableAllInfo()
// acceptPackages(packages)方法接受一个包名字符串数组,扫描器只会扫描这些包及其子包
.acceptPackages(packages)
// 执行扫描
.scan()) {
// getAllClasses()方法获取扫描结果中的所有类
// loadClasses()方法加载这些类并返回一个Class对象的数组
return scan.getAllClasses().loadClasses();
} // scan对象自动关闭
}
/**
* 扫描指定的包,并返回指定接口的实现类对象
*
* @param clazz 接口类
* @param packages 要扫描的包名
* @return 实现指定接口的类对象列表
*/
public static List<Class<?>> scan(Class<?> clazz, String... packages) {
List<Class<?>> list = new ArrayList<>();
// 遍历扫描到的每一个类
ScanUtil.scan(packages).forEach(aClass -> {
// 判断扫描到的类是否为指定接口的实现类,并排除接口自己
if (clazz.isAssignableFrom(aClass) && clazz != aClass) {
list.add(aClass);
}
});
return list;
}
/**
* 扫描指定的包,并返回带有指定注解的类对象
*
* @param annotation 指定的注解
* @param packages 要扫描的包名
* @return 带有指定注解的类对象列表
*/
public static List<Class<?>> scan(Annotation annotation, String... packages) {
List<Class<?>> list = new ArrayList<>();
ScanUtil.scan(packages).forEach(aClass -> {
// 判断扫描到的类是否带有指定的注解
if (aClass.isAnnotation() && aClass.isAnnotationPresent(annotation.getClass())) {
list.add(aClass);
}
});
return list;
}
/**
* 扫描指定的包,并返回实现了指定接口且带有指定注解的类
*
* @param clazz 接口类
* @param annotation 指定的注解
* @param packages 要扫描的包名
* @return 实现了指定接口且带有指定注解的类对象列表
*/
public static List<Class<?>> scan(Class<?> clazz, Annotation annotation, String... packages) {
List<Class<?>> listImpl = ScanUtil.scan(clazz, packages);
List<Class<?>> list = new ArrayList<>();
listImpl.forEach(aClass -> {
// 判断实现了指定接口的类是否带有指定的注解
if (aClass.isAnnotation() && aClass.isAnnotationPresent(annotation.getClass())) {
list.add(aClass);
}
});
return list;
}
}