diff --git a/hutool-core/src/main/java/cn/hutool/core/annotation/AnnotationUtil.java b/hutool-core/src/main/java/cn/hutool/core/annotation/AnnotationUtil.java
index be44f080a..c84de0073 100644
--- a/hutool-core/src/main/java/cn/hutool/core/annotation/AnnotationUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/annotation/AnnotationUtil.java
@@ -4,18 +4,14 @@ import cn.hutool.core.exceptions.UtilException;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ReflectUtil;
-import java.lang.annotation.Annotation;
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Inherited;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
+import java.lang.annotation.*;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Map;
+import java.util.Set;
/**
* 注解工具类
@@ -50,6 +46,47 @@ public class AnnotationUtil {
return (null == annotationEle) ? null : (isToCombination ? toCombination(annotationEle) : annotationEle).getAnnotations();
}
+ /**
+ * 获取可重复的注解列表
+ * 用于带有同一个注解的多个组合注解
+ *
+ * @param annotationEle {@link AnnotatedElement},可以是Class、Method、Field、Constructor、ReflectPermission
+ * @param annotationType 注解类型
+ * @return 注解列表
+ * @param 注解值类型
+ */
+ public static Set getRepeatedAnnotations(AnnotatedElement annotationEle, Class annotationType) {
+ if (!Annotation.class.isAssignableFrom(annotationType)){
+ return null;
+ }
+ Set annotationList = new HashSet<>();
+ recursion(annotationList, annotationEle.getAnnotations(), annotationType);
+ return annotationList;
+ }
+
+ /**
+ * 递归获取注解列表
+ *
+ * @param list 注解结果集
+ * @param annotations 注解参数集
+ * @param annotationType 注解类型
+ * @param 注解值类型
+ */
+ private static void recursion(Set list, Annotation[] annotations, Class annotationType) {
+ for (Annotation annotation : annotations) {
+ Class extends Annotation> clazz = annotation.getClass();
+ if (annotationType.isAssignableFrom(clazz)) {
+ list.add((T) annotation);
+ } else if (!Retention.class.isAssignableFrom(clazz)
+ && !Target.class.isAssignableFrom(clazz)
+ && !Documented.class.isAssignableFrom(clazz)
+ && !Repeatable.class.isAssignableFrom(clazz)
+ && !Inherited.class.isAssignableFrom(clazz)) {
+ recursion(list, annotation.annotationType().getAnnotations(), annotationType);
+ }
+ }
+ }
+
/**
* 获取指定注解
*
diff --git a/hutool-core/src/test/java/cn/hutool/core/annotation/AnnotationUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/annotation/AnnotationUtilTest.java
index 3340dcf37..c3077a626 100644
--- a/hutool-core/src/test/java/cn/hutool/core/annotation/AnnotationUtilTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/annotation/AnnotationUtilTest.java
@@ -3,7 +3,14 @@ package cn.hutool.core.annotation;
import org.junit.Assert;
import org.junit.Test;
+import java.util.Set;
+
public class AnnotationUtilTest {
+ @Test
+ public void getRepeatAnnotationValueTest(){
+ Set annotations = AnnotationUtil.getRepeatedAnnotations(ClassWithAnnotation.class, AnnotationForTest.class);
+ Assert.assertTrue(annotations != null && annotations.size() == 2);
+ }
@Test
public void getAnnotationValueTest() {
@@ -23,6 +30,7 @@ public class AnnotationUtilTest {
}
@AnnotationForTest("测试")
+ @RepeatAnnotationForTest
static class ClassWithAnnotation{
public void test(){
diff --git a/hutool-core/src/test/java/cn/hutool/core/annotation/RepeatAnnotationForTest.java b/hutool-core/src/test/java/cn/hutool/core/annotation/RepeatAnnotationForTest.java
new file mode 100644
index 000000000..cc71c68da
--- /dev/null
+++ b/hutool-core/src/test/java/cn/hutool/core/annotation/RepeatAnnotationForTest.java
@@ -0,0 +1,16 @@
+package cn.hutool.core.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @author hongda.li 2022-04-26 17:09
+ */
+@AnnotationForTest("repeat-annotation")
+@Retention(RetentionPolicy.RUNTIME)
+// Target注解决定MyAnnotation注解可以加在哪些成分上,如加在类身上,或者属性身上,或者方法身上等成分
+@Target({ ElementType.METHOD, ElementType.TYPE })
+public @interface RepeatAnnotationForTest {
+}