diff --git a/hutool-core/src/main/java/cn/hutool/v7/core/annotation/AnnotationUtil.java b/hutool-core/src/main/java/cn/hutool/v7/core/annotation/AnnotationUtil.java index d122e59dd0..4fe4ef63cf 100644 --- a/hutool-core/src/main/java/cn/hutool/v7/core/annotation/AnnotationUtil.java +++ b/hutool-core/src/main/java/cn/hutool/v7/core/annotation/AnnotationUtil.java @@ -19,6 +19,7 @@ package cn.hutool.v7.core.annotation; import cn.hutool.v7.core.annotation.elements.CombinationAnnotatedElement; import cn.hutool.v7.core.array.ArrayUtil; import cn.hutool.v7.core.classloader.ClassLoaderUtil; +import cn.hutool.v7.core.collection.set.SetUtil; import cn.hutool.v7.core.exception.HutoolException; import cn.hutool.v7.core.func.LambdaInfo; import cn.hutool.v7.core.func.LambdaUtil; @@ -26,7 +27,6 @@ import cn.hutool.v7.core.func.SerFunction; import cn.hutool.v7.core.map.reference.WeakConcurrentMap; import cn.hutool.v7.core.reflect.FieldUtil; import cn.hutool.v7.core.reflect.method.MethodUtil; -import cn.hutool.v7.core.text.CharSequenceUtil; import cn.hutool.v7.core.text.StrUtil; import cn.hutool.v7.core.util.ObjUtil; @@ -34,6 +34,7 @@ import java.lang.annotation.*; import java.lang.reflect.*; import java.util.HashMap; import java.util.Map; +import java.util.Set; import java.util.function.Predicate; import java.util.stream.Stream; @@ -51,11 +52,35 @@ public class AnnotationUtil { private static final String HUTOOL_MEMBER_ATTRIBUTE = "valueCache"; private static final String SPRING_INVOCATION_HANDLER = "SynthesizedMergedAnnotationInvocationHandler"; + /** + * 元注解 + */ + private static final Set> META_ANNOTATIONS = SetUtil.of( + Target.class, // + Retention.class, // + Inherited.class, // + Documented.class, // + SuppressWarnings.class, // + Override.class, // + Deprecated.class// + ); + /** * 直接声明的注解缓存 */ private static final Map DECLARED_ANNOTATIONS_CACHE = new WeakConcurrentMap<>(); + /** + * 判断注解是否为元注解 + * + * @param annotationType 注解类型 + * @return 是否为元注解 + * @since 7.0.0 + */ + public static boolean isMetaAnnotation(final Class annotationType) { + return META_ANNOTATIONS.contains(annotationType); + } + /** * 将指定的被注解的元素转换为组合注解元素 * @@ -70,6 +95,7 @@ public class AnnotationUtil { } // region ----- getAnnotation + /** * 获取直接声明的注解,若已有缓存则从缓存中获取 * @@ -118,7 +144,7 @@ public class AnnotationUtil { @SuppressWarnings("unchecked") public static T[] getAnnotations(final AnnotatedElement annotationEle, final boolean isToCombination, final Class annotationType) { final Annotation[] annotations = getAnnotations(annotationEle, isToCombination, - (annotation -> null == annotationType || annotationType.isAssignableFrom(annotation.getClass()))); + (annotation -> null == annotationType || annotationType.isAssignableFrom(annotation.getClass()))); final T[] result = ArrayUtil.newArray(annotationType, annotations.length); for (int i = 0; i < annotations.length; i++) { @@ -172,7 +198,7 @@ public class AnnotationUtil { * 检查是否包含指定注解
* 注解类传入全名,通过{@link Class#forName(String)}加载,避免不存在的注解导致的ClassNotFoundException * - * @param annotationEle {@link AnnotatedElement},可以是Class、Method、Field、Constructor、ReflectPermission + * @param annotationEle {@link AnnotatedElement},可以是Class、Method、Field、Constructor、ReflectPermission * @param annotationTypeName 注解类型完整类名 * @return 是否包含指定注解 * @since 6.0.0 @@ -186,7 +212,7 @@ public class AnnotationUtil { } catch (final ClassNotFoundException e) { // ignore } - if(null != aClass){ + if (null != aClass) { return hasAnnotation(annotationEle, aClass); } return false; @@ -205,6 +231,7 @@ public class AnnotationUtil { } // region ----- getAnnotationValue + /** * 获取指定注解默认值
* 如果无指定的属性方法返回null @@ -223,21 +250,21 @@ public class AnnotationUtil { * 获取指定注解属性的值
* 如果无指定的属性方法返回null * - * @param 注解类型 - * @param 注解类型值 - * @param annotationEle {@link AnnotatedElement},可以是Class、Method、Field、Constructor、ReflectPermission - * @param propertyName 属性名,例如注解中定义了name()方法,则 此处传入name + * @param 注解类型 + * @param 注解类型值 + * @param annotationEle {@link AnnotatedElement},可以是Class、Method、Field、Constructor、ReflectPermission + * @param propertyName 属性名,例如注解中定义了name()方法,则 此处传入name * @return 注解对象 * @throws HutoolException 调用注解中的方法时执行异常 */ - public static R getAnnotationValue(final AnnotatedElement annotationEle, final SerFunction propertyName) { - if(propertyName == null) { + public static R getAnnotationValue(final AnnotatedElement annotationEle, final SerFunction propertyName) { + if (propertyName == null) { return null; - }else { + } else { final LambdaInfo lambda = LambdaUtil.resolve(propertyName); final String instantiatedMethodType = lambda.getLambda().getInstantiatedMethodType(); final Class annotationClass = ClassLoaderUtil.loadClass(StrUtil.sub(instantiatedMethodType, 2, StrUtil.indexOf(instantiatedMethodType, ';'))); - return getAnnotationValue(annotationEle,annotationClass, lambda.getLambda().getImplMethodName()); + return getAnnotationValue(annotationEle, annotationClass, lambda.getLambda().getImplMethodName()); } } @@ -286,8 +313,8 @@ public class AnnotationUtil { final String name = t.getName(); // 跳过自有的几个方法 return (!"hashCode".equals(name)) // - && (!"toString".equals(name)) // - && (!"annotationType".equals(name)); + && (!"toString".equals(name)) // + && (!"annotationType".equals(name)); } return false; }); @@ -301,6 +328,7 @@ public class AnnotationUtil { // endregion // region ----- 元注解相关 + /** * 获取注解类的保留时间,可选值 SOURCE(源码时),CLASS(编译时),RUNTIME(运行时),默认为 CLASS * diff --git a/hutool-core/src/main/java/cn/hutool/v7/core/annotation/elements/CombinationAnnotatedElement.java b/hutool-core/src/main/java/cn/hutool/v7/core/annotation/elements/CombinationAnnotatedElement.java index f508f2ef66..705c44273d 100644 --- a/hutool-core/src/main/java/cn/hutool/v7/core/annotation/elements/CombinationAnnotatedElement.java +++ b/hutool-core/src/main/java/cn/hutool/v7/core/annotation/elements/CombinationAnnotatedElement.java @@ -21,6 +21,7 @@ import cn.hutool.v7.core.array.ArrayUtil; import cn.hutool.v7.core.collection.set.SetUtil; import cn.hutool.v7.core.map.TableMap; +import java.io.Serial; import java.io.Serializable; import java.lang.annotation.*; import java.lang.reflect.AnnotatedElement; @@ -38,6 +39,7 @@ import java.util.function.Predicate; **/ public class CombinationAnnotatedElement implements AnnotatedElement, Serializable { + @Serial private static final long serialVersionUID = 1L; /** @@ -52,19 +54,6 @@ public class CombinationAnnotatedElement implements AnnotatedElement, Serializab return new CombinationAnnotatedElement(element, predicate); } - /** - * 元注解 - */ - private static final Set> META_ANNOTATIONS = SetUtil.of( - Target.class, // - Retention.class, // - Inherited.class, // - Documented.class, // - SuppressWarnings.class, // - Override.class, // - Deprecated.class// - ); - /** * 注解类型与注解对象对应表 */ @@ -158,7 +147,7 @@ public class CombinationAnnotatedElement implements AnnotatedElement, Serializab // 直接注解 for (final Annotation annotation : annotations) { annotationType = annotation.annotationType(); - if (!META_ANNOTATIONS.contains(annotationType) + if (!AnnotationUtil.isMetaAnnotation(annotationType) // issue#I5FQGW@Gitee:跳过元注解和已经处理过的注解,防止递归调用 && !declaredAnnotationMap.containsKey(annotationType)) { if (test(annotation)) { @@ -183,7 +172,7 @@ public class CombinationAnnotatedElement implements AnnotatedElement, Serializab Class annotationType; for (final Annotation annotation : annotations) { annotationType = annotation.annotationType(); - if (!META_ANNOTATIONS.contains(annotationType) + if (!AnnotationUtil.isMetaAnnotation(annotationType) // issue#I5FQGW@Gitee:跳过元注解和已经处理过的注解,防止递归调用 && !annotationMap.containsKey(annotationType)) { if (test(annotation)) { diff --git a/hutool-core/src/test/java/cn/hutool/v7/core/annotation/AnnotationUtilTest.java b/hutool-core/src/test/java/cn/hutool/v7/core/annotation/AnnotationUtilTest.java index 2e6edd22e2..67ee6b83f3 100644 --- a/hutool-core/src/test/java/cn/hutool/v7/core/annotation/AnnotationUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/v7/core/annotation/AnnotationUtilTest.java @@ -171,6 +171,12 @@ public class AnnotationUtilTest { Assertions.assertTrue(ArrayUtil.equals(names, new String[]{"测试1", "测试2"})); } + @Test + void isMetaAnnotationTest() { + Assertions.assertTrue(AnnotationUtil.isMetaAnnotation(Deprecated.class)); + Assertions.assertFalse(AnnotationUtil.isMetaAnnotation(AnnotationForTest.class)); + } + @Target(ElementType.TYPE_USE) @Retention(RetentionPolicy.RUNTIME) private @interface MetaAnnotationForTest{