[程序设计]注解开发工具类:根据注解获取其所标记的类属性和方法
Posted 小兔子乖乖z
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[程序设计]注解开发工具类:根据注解获取其所标记的类属性和方法相关的知识,希望对你有一定的参考价值。
注解开发工具类,主要是根据注解获取对应的类、属性和方法。突然的一个想法做出来,我也不知道有没有用,还有一些想做的功能会在之后慢慢更新。
附Gitee仓库:AnnotationUtils
package pers.LovelyBunny.AnnotationUtils.utils;
import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
/**
*
* 注解开发工具类
*
* 全局静态方法调用,不需要实例化对象
*
* @author 张泽楠
* @since 2021-06-18
* @version 1.0
*
*/
public class AnnotationUtils {
/** 扫描根路径{@value} */
private static String rootPath;
/** 类名列表{@value} */
private static List<String> nameList = new ArrayList<String>();
/** 注解列表{@value} */
private static List<Class<Annotation>> annotationList = new ArrayList<Class<Annotation>>();
/** 类表{注解名: 类}{@value} */
private static Map<String, List<Class<?>>> classPool = new HashMap<String, List<Class<?>>>();
/** 接口表{注解名: 接口}{@value} */
private static Map<String, List<Class<?>>> interfacePool = new HashMap<String, List<Class<?>>>();
/** 枚举类表{注解名: 枚举类}{@value} */
private static Map<String, List<Class<?>>> enumPool = new HashMap<String, List<Class<?>>>();
/** 属性表{注解名: {类名: 属性列表}}{@value} */
private static Map<String, Map<String, List<Field>>> fieldPool = new HashMap<String, Map<String, List<Field>>>();
/** 方法表{注解名: {类名: 方法列表}}{@value} */
private static Map<String, Map<String, List<Method>>> methodPool = new HashMap<String, Map<String, List<Method>>>();
/**
* 程序加载时自动调用初始化函数{@link pers.LovelyBunny.AnnotationUtils.utils.AnnotationUtils#init()}
*/
static {
try {
init();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 不需要实例化对象
*/
private AnnotationUtils() {
super();
}
/**
*
* AnnotationUtils初始化
*
* @throws Exception
*/
private static void init() throws Exception {
System.out.println("----------------AnnotationUtils init begin----------------");
// 获取class根路径
String runModel = AnnotationUtils.class.getResource("").getProtocol();
// 判断运行模式,扫描包获取所有class的全限定类名,并保存在nameList中
if ("file" == runModel) {
rootPath = AnnotationUtils.class.getResource("/").toString().replace("file:/", "").replace("\\\\", "/");
scanPackageInFile(new File(rootPath));
} else if ("jar" == runModel) {
rootPath = AnnotationUtils.class.getProtectionDomain().getCodeSource().getLocation().getPath();
scanPackageInJar();
} else {
System.out.println("----------------AnnotationUtils init failure----------------");
return;
}
// 根据注解和类对所有class分类
sortClass();
System.out.println("----------------AnnotationUtils init finished----------------");
}
/**
*
* 扫描jar包,获取所有class的全限定类名
*
* @throws IOException
*/
private static void scanPackageInJar() throws IOException {
JarFile jarFile = new JarFile(new File(rootPath));
Enumeration<JarEntry> entrys = jarFile.entries();
while (entrys.hasMoreElements()) {
JarEntry jar = entrys.nextElement();
String name = jar.getName();
if (name.endsWith(".class")) {
nameList.add(name.replace("\\\\", "/").replace(".class", "").replace("/", "."));
}
}
jarFile.close();
}
/**
*
* 递归扫描包,获取所有class的全限定类名
*
* @param nodeFile
* 递归节点文件
* @throws Exception
*/
private static void scanPackageInFile(File nodeFile) throws Exception {
File[] filesList = nodeFile.listFiles();
for (File file : filesList) {
if (file.isDirectory()) {
scanPackageInFile(file);
} else {
if (file.getAbsolutePath().endsWith(".class")) {
// 将class路径转换为全限定类名
nameList.add(file.getAbsolutePath().replace("\\\\", "/").replace(rootPath, "").replace(".class", "")
.replace("/", "."));
}
}
}
}
/**
*
* 根据注解和类对所有class分类
*
* @throws Exception
*/
private static void sortClass() throws Exception {
// 获取所有注解类并保存
for (String className : nameList) {
Class<?> clazz = Class.forName(className);
if (clazz.isAnnotation()) {
System.out.println("[AnnotationUtils] Scanning annotation: " + className);
@SuppressWarnings("unchecked")
Class<Annotation> annotation = (Class<Annotation>) clazz;
annotationList.add(annotation);
}
}
// 遍历所有类
for (String className : nameList) {
Class<?> clazz = Class.forName(className);
// 跳过所有注解类
if (clazz.isAnnotation()) {
continue;
}
// 获取当前遍历类的所有属性
Field[] fields = clazz.getFields();
// 获取当前遍历类的所有方法
Method[] methods = clazz.getMethods();
// 遍历所有注解
for (Class<Annotation> annotation : annotationList) {
String annotationName = annotation.getName();
// 当前遍历类拥有当前遍历注解,则根据注解和当前遍历类的类型进行分类保存
if (null != clazz.getAnnotation(annotation)) {
if (clazz.isInterface()) {
System.out.println("[AnnotationUtils] Scanning class(interface): " + className);
if (interfacePool.containsKey(annotationName)) {
List<Class<?>> list = interfacePool.get(annotationName);
list.add(clazz);
interfacePool.put(annotationName, list);
} else {
List<Class<?>> list = new ArrayList<Class<?>>();
list.add(clazz);
interfacePool.put(annotationName, list);
}
} else if (clazz.isEnum()) {
System.out.println("[AnnotationUtils] Scanning class(enum): " + className);
if (enumPool.containsKey(annotationName)) {
List<Class<?>> list = enumPool.get(annotationName);
list.add(clazz);
enumPool.put(annotationName, list);
} else {
List<Class<?>> list = new ArrayList<Class<?>>();
list.add(clazz);
enumPool.put(annotationName, list);
}
} else {
System.out.println("[AnnotationUtils] Scanning class: " + className);
if (classPool.containsKey(annotationName)) {
List<Class<?>> list = classPool.get(annotationName);
list.add(clazz);
classPool.put(annotationName, list);
} else {
List<Class<?>> list = new ArrayList<Class<?>>();
list.add(clazz);
classPool.put(annotationName, list);
}
}
}
// 遍历当前遍历类的所有属性
for (Field field : fields) {
// 当前遍历属性拥有当前遍历注解,则根据注解和当前遍历属性的所属类进行分类保存
if (null != field.getAnnotation(annotation)) {
Map<String, List<Field>> map = null;
List<Field> list = null;
if (fieldPool.containsKey(annotationName)) {
map = fieldPool.get(annotationName);
if (map.containsKey(className)) {
list = map.get(className);
} else {
list = new ArrayList<Field>();
}
} else {
map = new HashMap<String, List<Field>>();
list = new ArrayList<Field>();
}
list.add(field);
map.put(className, list);
fieldPool.put(annotationName, map);
}
}
// 遍历当前遍历类的所有方法
for (Method method : methods) {
// 当前遍历属性拥有当前遍历注解,则根据注解和当前遍历属性的所属类进行分类保存
if (null != method.getAnnotation(annotation)) {
Map<String, List<Method>> map = null;
List<Method> list = null;
if (methodPool.containsKey(annotationName)) {
map = methodPool.get(annotationName);
if (map.containsKey(className)) {
list = map.get(className);
} else {
list = new ArrayList<Method>();
}
} else {
map = new HashMap<String, List<Method>>();
list = new ArrayList<Method>();
}
list.add(method);
map.put(className, list);
methodPool.put(annotationName, map);
}
}
}
}
}
/**
*
* 根据注解查询类
*
* @param annotation
* 所查询的注解类
* @return 所有拥有所查询注解的类的ArrayList,如果未查询到结果或所传入类不是一个注解,则返回{@code null}
*/
public static List<Class<?>> getClasssByAnnotation(Class<?> annotation) {
// 判断传入类是否为注解
if (!annotation.isAnnotation()) {
return null;
}
String annotationName = annotation.getName();
List<Class<?>> result = null;
if (classPool.containsKey(annotationName)) {
result = classPool.get(annotationName);
}
return result;
}
/**
*
* 根据注解查询接口
*
* @param annotation
* 所查询的注解类
* @return 所有拥有所查询注解的接口的ArrayList,如果未查询到结果或所传入类不是一个注解,则返回{@code null}
*/
public static List<Class<?>> getInterfacesByAnnotation(Class<?> annotation) {
// 判断传以上是关于[程序设计]注解开发工具类:根据注解获取其所标记的类属性和方法的主要内容,如果未能解决你的问题,请参考以下文章