All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.magictools.core.annotation.AnnotationUtil Maven / Gradle / Ivy

Go to download

magic-tools 是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。

The newest version!
package com.magictools.core.annotation;

import com.magictools.core.annotation.scanner.*;
import com.magictools.core.collection.CollUtil;
import com.magictools.core.exceptions.UtilException;
import com.magictools.core.lang.Assert;
import com.magictools.core.lang.Opt;
import com.magictools.core.util.ArrayUtil;
import com.magictools.core.util.ClassUtil;
import com.magictools.core.util.ObjectUtil;
import com.magictools.core.util.ReflectUtil;

import java.lang.annotation.*;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 注解工具类
* 快速获取注解对象、注解值等工具封装 * * @author looly * @since 4.0.9 */ public class AnnotationUtil { /** * 元注解 */ static final Set> META_ANNOTATIONS = CollUtil.newHashSet(Target.class, // Retention.class, // Inherited.class, // Documented.class, // SuppressWarnings.class, // Override.class, // Deprecated.class// ); /** * 是否为Jdk自带的元注解。
* 包括: *
    *
  • {@link Target}
  • *
  • {@link Retention}
  • *
  • {@link Inherited}
  • *
  • {@link Documented}
  • *
  • {@link SuppressWarnings}
  • *
  • {@link Override}
  • *
  • {@link Deprecated}
  • *
* * @param annotationType 注解类型 * @return 是否为Jdk自带的元注解 */ public static boolean isJdkMetaAnnotation(Class annotationType) { return META_ANNOTATIONS.contains(annotationType); } /** * 是否不为Jdk自带的元注解。
* 包括: *
    *
  • {@link Target}
  • *
  • {@link Retention}
  • *
  • {@link Inherited}
  • *
  • {@link Documented}
  • *
  • {@link SuppressWarnings}
  • *
  • {@link Override}
  • *
  • {@link Deprecated}
  • *
* * @param annotationType 注解类型 * @return 是否为Jdk自带的元注解 */ public static boolean isNotJdkMateAnnotation(Class annotationType) { return false == isJdkMetaAnnotation(annotationType); } /** * 将指定的被注解的元素转换为组合注解元素 * * @param annotationEle 注解元素 * @return 组合注解元素 */ public static CombinationAnnotationElement toCombination(AnnotatedElement annotationEle) { if (annotationEle instanceof CombinationAnnotationElement) { return (CombinationAnnotationElement) annotationEle; } return new CombinationAnnotationElement(annotationEle); } /** * 获取指定注解 * * @param annotationEle {@link AnnotatedElement},可以是Class、Method、Field、Constructor、ReflectPermission * @param isToCombination 是否为转换为组合注解,组合注解可以递归获取注解的注解 * @return 注解对象 */ public static Annotation[] getAnnotations(AnnotatedElement annotationEle, boolean isToCombination) { return getAnnotations(annotationEle, isToCombination, (Predicate) null); } /** * 获取组合注解 * * @param 注解类型 * @param annotationEle {@link AnnotatedElement},可以是Class、Method、Field、Constructor、ReflectPermission * @param annotationType 限定的 * @return 注解对象数组 * @since 5.8.0 */ public static T[] getCombinationAnnotations(AnnotatedElement annotationEle, Class annotationType) { return getAnnotations(annotationEle, true, annotationType); } /** * 获取指定注解 * * @param 注解类型 * @param annotationEle {@link AnnotatedElement},可以是Class、Method、Field、Constructor、ReflectPermission * @param isToCombination 是否为转换为组合注解,组合注解可以递归获取注解的注解 * @param annotationType 限定的 * @return 注解对象数组 * @since 5.8.0 */ public static T[] getAnnotations(AnnotatedElement annotationEle, boolean isToCombination, Class annotationType) { final Annotation[] annotations = getAnnotations(annotationEle, isToCombination, (annotation -> null == annotationType || annotationType.isAssignableFrom(annotation.getClass()))); final T[] result = ArrayUtil.newArray(annotationType, annotations.length); for (int i = 0; i < annotations.length; i++) { //noinspection unchecked result[i] = (T) annotations[i]; } return result; } /** * 获取指定注解 * * @param annotationEle {@link AnnotatedElement},可以是Class、Method、Field、Constructor、ReflectPermission * @param isToCombination 是否为转换为组合注解,组合注解可以递归获取注解的注解 * @param predicate 过滤器,{@link Predicate#test(Object)}返回{@code true}保留,否则不保留 * @return 注解对象 * @since 5.8.0 */ public static Annotation[] getAnnotations(AnnotatedElement annotationEle, boolean isToCombination, Predicate predicate) { if (null == annotationEle) { return null; } if (isToCombination) { if (null == predicate) { return toCombination(annotationEle).getAnnotations(); } return CombinationAnnotationElement.of(annotationEle, predicate).getAnnotations(); } final Annotation[] result = annotationEle.getAnnotations(); if (null == predicate) { return result; } return ArrayUtil.filter(result, predicate::test); } /** * 获取指定注解 * * @param 注解类型 * @param annotationEle {@link AnnotatedElement},可以是Class、Method、Field、Constructor、ReflectPermission * @param annotationType 注解类型 * @return 注解对象 */ public static A getAnnotation(AnnotatedElement annotationEle, Class annotationType) { return (null == annotationEle) ? null : toCombination(annotationEle).getAnnotation(annotationType); } /** * 检查是否包含指定注解指定注解 * * @param annotationEle {@link AnnotatedElement},可以是Class、Method、Field、Constructor、ReflectPermission * @param annotationType 注解类型 * @return 是否包含指定注解 * @since 5.4.2 */ public static boolean hasAnnotation(AnnotatedElement annotationEle, Class annotationType) { return null != getAnnotation(annotationEle, annotationType); } /** * 获取指定注解默认值
* 如果无指定的属性方法返回null * * @param 注解值类型 * @param annotationEle {@link AnnotatedElement},可以是Class、Method、Field、Constructor、ReflectPermission * @param annotationType 注解类型 * @return 注解对象 * @throws UtilException 调用注解中的方法时执行异常 */ public static T getAnnotationValue(AnnotatedElement annotationEle, Class annotationType) throws UtilException { return getAnnotationValue(annotationEle, annotationType, "value"); } /** * 获取指定注解属性的值
* 如果无指定的属性方法返回null * * @param 注解值类型 * @param annotationEle {@link AnnotatedElement},可以是Class、Method、Field、Constructor、ReflectPermission * @param annotationType 注解类型 * @param propertyName 属性名,例如注解中定义了name()方法,则 此处传入name * @return 注解对象 * @throws UtilException 调用注解中的方法时执行异常 */ public static T getAnnotationValue(AnnotatedElement annotationEle, Class annotationType, String propertyName) throws UtilException { final Annotation annotation = getAnnotation(annotationEle, annotationType); if (null == annotation) { return null; } final Method method = ReflectUtil.getMethodOfObj(annotation, propertyName); if (null == method) { return null; } return ReflectUtil.invoke(annotation, method); } /** * 获取指定注解中所有属性值
* 如果无指定的属性方法返回null * * @param annotationEle {@link AnnotatedElement},可以是Class、Method、Field、Constructor、ReflectPermission * @param annotationType 注解类型 * @return 注解对象 * @throws UtilException 调用注解中的方法时执行异常 */ public static Map getAnnotationValueMap(AnnotatedElement annotationEle, Class annotationType) throws UtilException { final Annotation annotation = getAnnotation(annotationEle, annotationType); if (null == annotation) { return null; } final Method[] methods = ReflectUtil.getMethods(annotationType, t -> { if (ArrayUtil.isEmpty(t.getParameterTypes())) { // 只读取无参方法 final String name = t.getName(); // 跳过自有的几个方法 return (false == "hashCode".equals(name)) // && (false == "toString".equals(name)) // && (false == "annotationType".equals(name)); } return false; }); final HashMap result = new HashMap<>(methods.length, 1); for (Method method : methods) { result.put(method.getName(), ReflectUtil.invoke(annotation, method)); } return result; } /** * 获取注解类的保留时间,可选值 SOURCE(源码时),CLASS(编译时),RUNTIME(运行时),默认为 CLASS * * @param annotationType 注解类 * @return 保留时间枚举 */ public static RetentionPolicy getRetentionPolicy(Class annotationType) { final Retention retention = annotationType.getAnnotation(Retention.class); if (null == retention) { return RetentionPolicy.CLASS; } return retention.value(); } /** * 获取注解类可以用来修饰哪些程序元素,如 TYPE, METHOD, CONSTRUCTOR, FIELD, PARAMETER 等 * * @param annotationType 注解类 * @return 注解修饰的程序元素数组 */ public static ElementType[] getTargetType(Class annotationType) { final Target target = annotationType.getAnnotation(Target.class); if (null == target) { return new ElementType[]{ElementType.TYPE, // ElementType.FIELD, // ElementType.METHOD, // ElementType.PARAMETER, // ElementType.CONSTRUCTOR, // ElementType.LOCAL_VARIABLE, // ElementType.ANNOTATION_TYPE, // ElementType.PACKAGE// }; } return target.value(); } /** * 是否会保存到 Javadoc 文档中 * * @param annotationType 注解类 * @return 是否会保存到 Javadoc 文档中 */ public static boolean isDocumented(Class annotationType) { return annotationType.isAnnotationPresent(Documented.class); } /** * 是否可以被继承,默认为 false * * @param annotationType 注解类 * @return 是否会保存到 Javadoc 文档中 */ public static boolean isInherited(Class annotationType) { return annotationType.isAnnotationPresent(Inherited.class); } /** * 设置新的注解的属性(字段)值 * * @param annotation 注解对象 * @param annotationField 注解属性(字段)名称 * @param value 要更新的属性值 * @since 5.5.2 */ @SuppressWarnings({"rawtypes", "unchecked"}) public static void setValue(Annotation annotation, String annotationField, Object value) { final Map memberValues = (Map) ReflectUtil.getFieldValue(Proxy.getInvocationHandler(annotation), "memberValues"); memberValues.put(annotationField, value); } /** * 获取别名支持后的注解 * * @param annotationEle 被注解的类 * @param annotationType 注解类型Class * @param 注解类型 * @return 别名支持后的注解 * @since 5.7.23 */ @SuppressWarnings("unchecked") public static T getAnnotationAlias(AnnotatedElement annotationEle, Class annotationType) { final T annotation = getAnnotation(annotationEle, annotationType); return (T) Proxy.newProxyInstance(annotationType.getClassLoader(), new Class[]{annotationType}, new AnnotationProxy<>(annotation)); } /** * 将指定注解实例与其元注解转为合成注解 * * @param annotation 注解 * @param annotationType 注解类型 * @param 注解类型 * @return 合成注解 * @see SyntheticAnnotation */ public static T getSynthesisAnnotation(Annotation annotation, Class annotationType) { return SyntheticAnnotation.of(annotation).getAnnotation(annotationType); } /** * 获取元素上所有指定注解 *
    *
  • 若元素是类,则递归解析全部父类和全部父接口上的注解;
  • *
  • 若元素是方法、属性或注解,则只解析其直接声明的注解;
  • *
* * @param annotatedElement 可注解元素 * @param annotationType 注解类型 * @param 注解类型 * @return 注解 * @see SyntheticAnnotation */ public static List getAllSynthesisAnnotations(AnnotatedElement annotatedElement, Class annotationType) { AnnotationScanner[] scanners = new AnnotationScanner[] { new MetaAnnotationScanner(), new TypeAnnotationScanner(), new MethodAnnotationScanner(), new FieldAnnotationScanner() }; return AnnotationScanner.scanByAnySupported(annotatedElement, scanners).stream() .map(SyntheticAnnotation::of) .map(annotation -> annotation.getAnnotation(annotationType)) .filter(Objects::nonNull) .collect(Collectors.toList()); } /** * 方法是否为注解属性方法。
* 方法无参数,且有返回值的方法认为是注解属性的方法。 * * @param method 方法 */ static boolean isAttributeMethod(Method method) { return method.getParameterCount() == 0 && method.getReturnType() != void.class; } /** * 获取注解的全部属性值获取方法 * * @param annotationType 注解 * @return 注解的全部属性值 * @throws IllegalArgumentException 当别名属性在注解中不存在,或别名属性的值与原属性的值类型不一致时抛出 */ static Map getAttributeMethods(Class annotationType) { // 获取全部注解属性值 Map attributeMethods = Stream.of(annotationType.getDeclaredMethods()) .filter(AnnotationUtil::isAttributeMethod) .collect(Collectors.toMap(Method::getName, Function.identity())); // 处理别名 attributeMethods.forEach((methodName, method) -> { String alias = Opt.ofNullable(method.getAnnotation(Alias.class)) .map(Alias::value) .orElse(null); if (ObjectUtil.isNull(alias)) { return; } // 存在别名,则将原本的值替换为别名对应的值 Assert.isTrue(attributeMethods.containsKey(alias), "No method for alias: [{}]", alias); Method aliasAttributeMethod = attributeMethods.get(alias); Assert.isTrue( ObjectUtil.isNull(aliasAttributeMethod) || ClassUtil.isAssignable(method.getReturnType(), aliasAttributeMethod.getReturnType()), "Return type of the alias method [{}] is inconsistent with the original [{}]", aliasAttributeMethod.getClass(), method.getParameterTypes() ); attributeMethods.put(methodName, aliasAttributeMethod); }); return attributeMethods; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy