, MetaAnnotation> getMetaAnnotationMap() {
+ return metaAnnotationMap;
+ }
+
+ /**
+ * 获取根注解类型
+ *
+ * @return java.lang.Class extends java.lang.annotation.Annotation>
+ */
+ @Override
+ public Class extends Annotation> annotationType() {
+ return getSource().annotationType();
+ }
+
+ /**
+ * 获取属性值,若存在{@link Alias}则获取{@link Alias#value()}指定的别名属性的值
+ * 当不同层级的注解之间存在同名属性时,将优先获取更接近根注解的属性
+ *
+ * @param attributeName 属性名
+ */
+ public Object getAttribute(String attributeName) {
+ return attributeCaches.computeIfAbsent(attributeName, a -> metaAnnotationMap.values()
+ .stream()
+ .filter(ma -> ma.hasAttribute(attributeName)) // 集合默认是根据distance有序的,故此处无需再排序
+ .findFirst()
+ .map(ma -> ma.getAttribute(attributeName))
+ .orElse(null)
+ );
+ }
+
+ /**
+ * 若合成注解在存在指定元注解,则使用动态代理生成一个对应的注解实例
+ *
+ * @param annotationType 注解类型
+ * @param 注解类型
+ * @return 注解
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ public T getAnnotation(Class annotationType) {
+ if (metaAnnotationMap.containsKey(annotationType)) {
+ return (T) Proxy.newProxyInstance(
+ annotationType.getClassLoader(),
+ new Class[]{annotationType, Synthesized.class},
+ new SyntheticAnnotationProxy<>(this, annotationType)
+ );
+ }
+ return null;
+ }
+
+ /**
+ * 获取全部注解
+ *
+ * @return java.lang.annotation.Annotation[]
+ */
+ @Override
+ public Annotation[] getAnnotations() {
+ return getMetaAnnotationMap().values().toArray(new MetaAnnotation[0]);
+ }
+
+ /**
+ * 获取根注解直接声明注解
+ *
+ * @return 直接声明注解
+ */
+ @Override
+ public Annotation[] getDeclaredAnnotations() {
+ return new Annotation[]{ getSource() };
+ }
+
+ /**
+ * 广度优先遍历并缓存该根注解上的全部元注解
+ */
+ private void loadMetaAnnotations() {
+ // 若该注解已经是合成注解,则直接使用已解析好的元注解信息
+ if (source instanceof SyntheticAnnotation.Synthesized) {
+ this.metaAnnotationMap.putAll(((Synthesized)source).getMetaAnnotationMap());
+ return;
+ }
+ // 扫描元注解
+ metaAnnotationMap.put(source.annotationType(), new MetaAnnotation(source, 0));
+ new MateAnnotationScanner().scan(
+ (index, annotation) -> metaAnnotationMap.computeIfAbsent(
+ // 当出现重复的注解时,由于后添加的注解必然层级更高,优先级更低,因此当直接忽略
+ annotation.annotationType(), t -> new MetaAnnotation(annotation, index)
+ ),
+ source.annotationType(), null
+ );
+ }
+
+ /**
+ * 元注解包装类
+ *
+ * @author huangchengxing
+ */
+ static class MetaAnnotation implements Annotation {
+
+ private final Annotation annotation;
+ private final Map attributeMethodCaches;
+ private final int distance;
+
+ public MetaAnnotation(Annotation annotation, int distance) {
+ this.annotation = annotation;
+ this.distance = distance;
+ this.attributeMethodCaches = AnnotationUtil.getAttributeMethods(annotation.annotationType());
+ }
+
+ /**
+ * 获取注解类型
+ *
+ * @return 注解类型
+ */
+ @Override
+ public Class extends Annotation> annotationType() {
+ return annotation.annotationType();
+ }
+
+ /**
+ * 获取元注解
+ *
+ * @return 元注解
+ */
+ public Annotation get() {
+ return annotation;
+ }
+
+ /**
+ * 获取根注解到元注解的距离
+ *
+ * @return 根注解到元注解的距离
+ */
+ public int getDistance() {
+ return distance;
+ }
+
+ /**
+ * 元注解是否存在该属性
+ *
+ * @param attributeName 属性名
+ * @return 是否存在该属性
+ */
+ public boolean hasAttribute(String attributeName) {
+ return attributeMethodCaches.containsKey(attributeName);
+ }
+
+ /**
+ * 获取元注解的属性值
+ *
+ * @param attributeName 属性名
+ * @return 元注解的属性值
+ */
+ public Object getAttribute(String attributeName) {
+ return Opt.ofNullable(attributeMethodCaches.get(attributeName))
+ .map(method -> ReflectUtil.invoke(annotation, method))
+ .orElse(null);
+ }
+
+ }
+
+ /**
+ * 表示一个已经被合成的注解
+ *
+ * @author huangchengxing
+ */
+ interface Synthesized {
+
+ /**
+ * 获取合成注解中已解析的元注解信息
+ *
+ * @return 合成注解中已解析的元注解信息
+ */
+ Map, MetaAnnotation> getMetaAnnotationMap();
+
+ static boolean isMetaAnnotationMapMethod(Method method) {
+ return StrUtil.equals("getMetaAnnotationMap", method.getName());
+ }
+
+ }
+
+ /**
+ * 合成注解代理类
+ *
+ * @author huangchengxing
+ */
+ static class SyntheticAnnotationProxy implements Annotation, InvocationHandler {
+
+ private final Class annotationType;
+ private final SyntheticAnnotation> syntheticAnnotation;
+
+ public SyntheticAnnotationProxy(SyntheticAnnotation> syntheticAnnotation, Class annotationType) {
+ this.syntheticAnnotation = syntheticAnnotation;
+ this.annotationType = annotationType;
+ }
+
+ @Override
+ public Class extends Annotation> annotationType() {
+ return annotationType;
+ }
+
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ if (Synthesized.isMetaAnnotationMapMethod(method)) {
+ return syntheticAnnotation.getMetaAnnotationMap();
+ }
+ if (ReflectUtil.isHashCodeMethod(method)) {
+ return getHashCode();
+ }
+ if (ReflectUtil.isToStringMethod(method)) {
+ return getToString();
+ }
+ return ObjectUtil.defaultIfNull(
+ syntheticAnnotation.getAttribute(method.getName()),
+ () -> ReflectUtil.invoke(this, method, args)
+ );
+ }
+
+ /**
+ * 获取toString值
+ *
+ * @return toString值
+ */
+ private String getToString() {
+ String attributes = Stream.of(annotationType().getDeclaredMethods())
+ .filter(AnnotationUtil::isAttributeMethod)
+ .map(method -> StrUtil.format("{}={}", method.getName(), syntheticAnnotation.getAttribute(method.getName())))
+ .collect(Collectors.joining(", "));
+ return StrUtil.format("@{}({})", annotationType().getName(), attributes);
+ }
+
+ /**
+ * 获取hashcode值
+ *
+ * @return hashcode值
+ */
+ private int getHashCode() {
+ return Objects.hash((Object)syntheticAnnotation.getAnnotations());
+ }
+
+ }
+}
diff --git a/hutool-core/src/test/java/cn/hutool/core/annotation/SyntheticAnnotationTest.java b/hutool-core/src/test/java/cn/hutool/core/annotation/SyntheticAnnotationTest.java
new file mode 100644
index 000000000..a81147e2e
--- /dev/null
+++ b/hutool-core/src/test/java/cn/hutool/core/annotation/SyntheticAnnotationTest.java
@@ -0,0 +1,81 @@
+package cn.hutool.core.annotation;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.lang.annotation.*;
+import java.util.Map;
+
+/**
+ * 合成注解{@link SyntheticAnnotation}的测试用例
+ *
+ * @author huangchengxing
+ */
+public class SyntheticAnnotationTest {
+
+ @Test
+ public void testSynthesisAnnotation() {
+ ChildAnnotation rootAnnotation = AnnotatedClass.class.getAnnotation(ChildAnnotation.class);
+ SyntheticAnnotation syntheticAnnotation = SyntheticAnnotation.of(rootAnnotation);
+ Assert.assertEquals(syntheticAnnotation.getSource(), rootAnnotation);
+ Assert.assertEquals(syntheticAnnotation.annotationType(), rootAnnotation.annotationType());
+ Assert.assertEquals(1, syntheticAnnotation.getDeclaredAnnotations().length);
+ Assert.assertEquals(syntheticAnnotation.getDeclaredAnnotations()[0], rootAnnotation);
+ Assert.assertEquals(3, syntheticAnnotation.getAnnotations().length);
+
+ Assert.assertEquals(syntheticAnnotation.getAttribute("childValue"), "Child!");
+ Assert.assertEquals(syntheticAnnotation.getAttribute("childValueAlias"), "Child!");
+ Assert.assertEquals(syntheticAnnotation.getAttribute("parentValue"), "Child's Parent!");
+ Assert.assertEquals(syntheticAnnotation.getAttribute("grandParentValue"), "Child's GrandParent!");
+
+ Map, SyntheticAnnotation.MetaAnnotation> annotationMap = syntheticAnnotation.getMetaAnnotationMap();
+ ChildAnnotation childAnnotation = syntheticAnnotation.getAnnotation(ChildAnnotation.class);
+ Assert.assertTrue(syntheticAnnotation.isAnnotationPresent(ChildAnnotation.class));
+ Assert.assertNotNull(childAnnotation);
+ Assert.assertEquals(childAnnotation.childValue(), "Child!");
+ Assert.assertEquals(childAnnotation.childValueAlias(), "Child!");
+ Assert.assertEquals(annotationMap, SyntheticAnnotation.of(childAnnotation).getMetaAnnotationMap());
+
+ ParentAnnotation parentAnnotation = syntheticAnnotation.getAnnotation(ParentAnnotation.class);
+ Assert.assertTrue(syntheticAnnotation.isAnnotationPresent(ParentAnnotation.class));
+ Assert.assertNotNull(parentAnnotation);
+ Assert.assertEquals(parentAnnotation.parentValue(), "Child's Parent!");
+ Assert.assertEquals(annotationMap, SyntheticAnnotation.of(parentAnnotation).getMetaAnnotationMap());
+
+ GrandParentAnnotation grandParentAnnotation = syntheticAnnotation.getAnnotation(GrandParentAnnotation.class);
+ Assert.assertTrue(syntheticAnnotation.isAnnotationPresent(GrandParentAnnotation.class));
+ Assert.assertNotNull(grandParentAnnotation);
+ Assert.assertEquals(grandParentAnnotation.grandParentValue(), "Child's GrandParent!");
+ Assert.assertEquals(annotationMap, SyntheticAnnotation.of(grandParentAnnotation).getMetaAnnotationMap());
+ }
+
+ // 注解结构如下:
+ // AnnotatedClass -> @ChildAnnotation -> @ParentAnnotation -> @GrandParentAnnotation
+ // -> @GrandParentAnnotation
+ @ChildAnnotation(childValueAlias = "Child!")
+ class AnnotatedClass {}
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ ElementType.ANNOTATION_TYPE })
+ @interface GrandParentAnnotation {
+ String grandParentValue() default "";
+ }
+
+ @GrandParentAnnotation(grandParentValue = "Parent's GrandParent!") // 覆盖元注解@GrandParentAnnotation的属性
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ ElementType.TYPE })
+ @interface ParentAnnotation {
+ String parentValue() default "";
+ }
+
+ @GrandParentAnnotation(grandParentValue = "Child's GrandParent!") // 重复的元注解,靠近根注解的优先级高
+ @ParentAnnotation(parentValue = "Child's Parent!") // 覆盖元注解@ParentAnnotation的属性
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ ElementType.METHOD, ElementType.TYPE })
+ @interface ChildAnnotation {
+ String childValueAlias() default "";
+ @Alias("childValueAlias")
+ String childValue() default "";
+ }
+
+}