Files
utils/src/main/java/com/hua/valid/AnnotationHandleFactory.java
2024-07-20 14:34:56 +08:00

148 lines
5.4 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.hua.valid;
import cn.hutool.core.util.ArrayUtil;
import com.hua.annotation.Handles;
import com.hua.valid.annotation.PackageScanConfig;
import org.reflections.Reflections;
import org.reflections.scanners.SubTypesScanner;
import org.reflections.scanners.TypeAnnotationsScanner;
import org.reflections.util.ClasspathHelper;
import org.reflections.util.ConfigurationBuilder;
import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.function.Consumer;
/**
* @author Hua
* @since 2024/7/18 下午2:43
*/
public class AnnotationHandleFactory {
// 缓存已加载的注解处理器
private static final Map<Class<? extends Annotation>, AnnotationHandler> cache = new HashMap<>();
private static boolean useSPI = true; // 是否使用SPI加载处理器
private static boolean useReflection = false; // 是否使用反射加载处理器
private static String[] packagesToScan = {"com.hua.valid"}; // 反射扫描的包路径
// 静态初始化块,在类加载时进行处理器初始化
static {
resolvePackageConfig();
initializeHandlers();
}
/**
* 配置处理器加载方式和扫描路径。
*
* @param useSpi 是否使用SPI加载处理器。
* @param useRef 是否使用反射加载处理器。
* @param packages 反射扫描的包路径。
*/
public static void configure(boolean useSpi, boolean useRef, String[] packages) {
useSPI = useSpi;
useReflection = useRef;
packagesToScan = packages;
cache.clear(); // 清除缓存
initializeHandlers(); // 重新初始化处理器
}
private static void resolvePackageConfig() {
Reflections reflections = new Reflections(new ConfigurationBuilder()
.setUrls(ClasspathHelper.forJavaClassPath())
.setScanners(new TypeAnnotationsScanner(), new SubTypesScanner()));
// 查找所有应用了PackageScanConfig注解的类
Set<Class<?>> configClasses = reflections.getTypesAnnotatedWith(PackageScanConfig.class);
if (configClasses.isEmpty()) {
return;
}
PackageScanConfig config = configClasses.stream().findFirst().get().getAnnotation(PackageScanConfig.class);
useSPI = config.useSPI();
useReflection = config.useReflection();
packagesToScan = config.packages();
}
// 初始化处理器根据配置决定使用SPI或反射加载
private static void initializeHandlers() {
if (useSPI) {
loadHandlersViaSPI();
}
if (useReflection) {
loadHandlersViaReflection();
}
}
// 通过SPI加载注解处理器
private static void loadHandlersViaSPI() {
ServiceLoader<AnnotationHandler> loadedHandlers = ServiceLoader.load(AnnotationHandler.class);
loadedHandlers.forEach(handler -> {
Handles handles = handler.getClass().getAnnotation(Handles.class);
if (handles != null) {
cache.put(handles.value(), handler);
}
});
}
// 通过反射加载注解处理器
private static void loadHandlersViaReflection() {
// 单独的方法用于加载处理器
Consumer<Reflections> loadHandlers = (reflections) -> {
reflections.getTypesAnnotatedWith(Handles.class).forEach(cls -> {
try {
AnnotationHandler handler = (AnnotationHandler) cls.getDeclaredConstructor().newInstance();
Handles handlesAnnotation = cls.getAnnotation(Handles.class);
cache.put(handlesAnnotation.value(), handler);
} catch (ReflectiveOperationException e) {
// 推荐使用日志记录异常,而非仅仅打印堆栈信息
e.printStackTrace();
}
});
};
if (ArrayUtil.isEmpty(packagesToScan)) {
Reflections reflections = new Reflections(new ConfigurationBuilder()
.setUrls(ClasspathHelper.forJavaClassPath())
.setScanners(new TypeAnnotationsScanner(), new SubTypesScanner()));
loadHandlers.accept(reflections);
} else {
for (String pkg : packagesToScan) {
Reflections reflections = new Reflections(new ConfigurationBuilder()
.forPackages(pkg)
.setScanners(new SubTypesScanner(), new TypeAnnotationsScanner()));
loadHandlers.accept(reflections);
}
}
}
/**
* 根据注解类型获取对应的处理器。
*
* @param annotation 注解实例。
* @return 对应的注解处理器如果未找到返回null。
*/
public static AnnotationHandler getHandler(Annotation annotation) {
return cache.get(annotation.annotationType());
}
/**
* 处理给定的注解数据对象。
*
* @param handleDTO 包含注解信息的数据传输对象。
* @return 处理结果,成功或失败。
*/
public static boolean handle(HandleDTO handleDTO) {
for (Annotation annotation : handleDTO.getAnnotations()) {
AnnotationHandler handler = getHandler(annotation);
if (handler != null) {
handleDTO.setCurrentAnnotation(annotation);
return handler.handle(handleDTO);
}
}
return true;
}
}