[程序设计]注解开发工具类:根据注解获取其所标记的类属性和方法

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) {
		// 判断传

以上是关于[程序设计]注解开发工具类:根据注解获取其所标记的类属性和方法的主要内容,如果未能解决你的问题,请参考以下文章

java注解

java注解

java注解的使用

java注解

java之注解

Java连载108-注解OverrideDeprecatedSuppressWarnings