diff --git a/hutool-core/src/main/java/cn/hutool/core/annotation/AbstractAnnotationAttributeWrapper.java b/hutool-core/src/main/java/cn/hutool/core/annotation/AbstractWrappedAnnotationAttribute.java similarity index 81% rename from hutool-core/src/main/java/cn/hutool/core/annotation/AbstractAnnotationAttributeWrapper.java rename to hutool-core/src/main/java/cn/hutool/core/annotation/AbstractWrappedAnnotationAttribute.java index 9d4c170cd..2dc13d476 100644 --- a/hutool-core/src/main/java/cn/hutool/core/annotation/AbstractAnnotationAttributeWrapper.java +++ b/hutool-core/src/main/java/cn/hutool/core/annotation/AbstractWrappedAnnotationAttribute.java @@ -8,19 +8,19 @@ import java.util.Collection; import java.util.List; /** - * {@link AnnotationAttributeWrapper}的基本实现 + * {@link WrappedAnnotationAttribute}的基本实现 * * @author huangchengxing * @see ForceAliasedAnnotationAttribute * @see AliasedAnnotationAttribute * @see MirroredAnnotationAttribute */ -public abstract class AbstractAnnotationAttributeWrapper implements AnnotationAttributeWrapper { +public abstract class AbstractWrappedAnnotationAttribute implements WrappedAnnotationAttribute { protected final AnnotationAttribute original; protected final AnnotationAttribute linked; - protected AbstractAnnotationAttributeWrapper(AnnotationAttribute original, AnnotationAttribute linked) { + protected AbstractWrappedAnnotationAttribute(AnnotationAttribute original, AnnotationAttribute linked) { Assert.notNull(original, "target must not null"); Assert.notNull(linked, "linked must not null"); this.original = original; @@ -43,7 +43,7 @@ public abstract class AbstractAnnotationAttributeWrapper implements AnnotationAt AnnotationAttribute next = original; while (next != null) { curr = next; - next = next.isWrapped() ? ((AnnotationAttributeWrapper)curr).getOriginal() : null; + next = next.isWrapped() ? ((WrappedAnnotationAttribute)curr).getOriginal() : null; } return curr; } @@ -63,7 +63,7 @@ public abstract class AbstractAnnotationAttributeWrapper implements AnnotationAt leafAttributes.add(curr); return; } - AnnotationAttributeWrapper wrappedAttribute = (AnnotationAttributeWrapper)curr; + WrappedAnnotationAttribute wrappedAttribute = (WrappedAnnotationAttribute)curr; collectLeafAttribute(wrappedAttribute.getOriginal(), leafAttributes); collectLeafAttribute(wrappedAttribute.getLinked(), leafAttributes); } diff --git a/hutool-core/src/main/java/cn/hutool/core/annotation/AliasAttributePostProcessor.java b/hutool-core/src/main/java/cn/hutool/core/annotation/AliasAttributePostProcessor.java index 8eba6bb49..3c0c2f0cf 100644 --- a/hutool-core/src/main/java/cn/hutool/core/annotation/AliasAttributePostProcessor.java +++ b/hutool-core/src/main/java/cn/hutool/core/annotation/AliasAttributePostProcessor.java @@ -25,7 +25,7 @@ public class AliasAttributePostProcessor implements SynthesizedAnnotationPostPro } @Override - public void process(SynthesizedAnnotation annotation, SyntheticAnnotation syntheticAnnotation) { + public void process(SynthesizedAnnotation annotation, SynthesizedAnnotationAggregator synthesizedAnnotationAggregator) { final Map attributeMap = annotation.getAttributes(); // 记录别名与属性的关系 @@ -47,7 +47,6 @@ public class AliasAttributePostProcessor implements SynthesizedAnnotationPostPro final AnnotationAttribute resolvedAttribute = Opt.ofNullable(attributeName) .map(attributeAliasMappings::getRootNode) .map(TreeEntry::getValue) - .map(aliasAttribute -> (AnnotationAttribute)new ForceAliasedAnnotationAttribute(attribute, aliasAttribute)) .orElse(attribute); Assert.isTrue( ObjectUtil.isNull(resolvedAttribute) @@ -55,7 +54,9 @@ public class AliasAttributePostProcessor implements SynthesizedAnnotationPostPro "return type of the root alias method [{}] is inconsistent with the original [{}]", resolvedAttribute.getClass(), attribute.getAttributeType() ); - attributeMap.put(attributeName, resolvedAttribute); + if (attribute != resolvedAttribute) { + attributeMap.put(attributeName, new ForceAliasedAnnotationAttribute(attribute, resolvedAttribute)); + } }); annotation.setAttributes(attributeMap); } diff --git a/hutool-core/src/main/java/cn/hutool/core/annotation/AliasForLinkAttributePostProcessor.java b/hutool-core/src/main/java/cn/hutool/core/annotation/AliasForLinkAttributePostProcessor.java index dcaff1438..4fbe48766 100644 --- a/hutool-core/src/main/java/cn/hutool/core/annotation/AliasForLinkAttributePostProcessor.java +++ b/hutool-core/src/main/java/cn/hutool/core/annotation/AliasForLinkAttributePostProcessor.java @@ -24,7 +24,7 @@ public class AliasForLinkAttributePostProcessor implements SynthesizedAnnotation } @Override - public void process(SynthesizedAnnotation annotation, SyntheticAnnotation syntheticAnnotation) { + public void process(SynthesizedAnnotation annotation, SynthesizedAnnotationAggregator synthesizedAnnotationAggregator) { final Map attributeMap = new HashMap<>(annotation.getAttributes()); attributeMap.forEach((originalAttributeName, originalAttribute) -> { // 获取注解 @@ -36,7 +36,7 @@ public class AliasForLinkAttributePostProcessor implements SynthesizedAnnotation } // 获取注解属性 - final SynthesizedAnnotation aliasAnnotation = SyntheticAnnotationUtil.getLinkedAnnotation(link, syntheticAnnotation, annotation.annotationType()); + final SynthesizedAnnotation aliasAnnotation = SyntheticAnnotationUtil.getLinkedAnnotation(link, synthesizedAnnotationAggregator, annotation.annotationType()); if (ObjectUtil.isNull(aliasAnnotation)) { return; } @@ -47,11 +47,11 @@ public class AliasForLinkAttributePostProcessor implements SynthesizedAnnotation // aliasFor if (RelationType.ALIAS_FOR.equals(link.type())) { - wrappingLinkedAttribute(syntheticAnnotation, originalAttribute, aliasAttribute, AliasedAnnotationAttribute::new); + wrappingLinkedAttribute(synthesizedAnnotationAggregator, originalAttribute, aliasAttribute, AliasedAnnotationAttribute::new); return; } // forceAliasFor - wrappingLinkedAttribute(syntheticAnnotation, originalAttribute, aliasAttribute, ForceAliasedAnnotationAttribute::new); + wrappingLinkedAttribute(synthesizedAnnotationAggregator, originalAttribute, aliasAttribute, ForceAliasedAnnotationAttribute::new); }); } @@ -59,16 +59,16 @@ public class AliasForLinkAttributePostProcessor implements SynthesizedAnnotation * 对指定注解属性进行包装,若该属性已被包装过,则递归以其为根节点的树结构,对树上全部的叶子节点进行包装 */ private void wrappingLinkedAttribute( - SyntheticAnnotation syntheticAnnotation, AnnotationAttribute originalAttribute, AnnotationAttribute aliasAttribute, BinaryOperator wrapping) { + SynthesizedAnnotationAggregator synthesizedAnnotationAggregator, AnnotationAttribute originalAttribute, AnnotationAttribute aliasAttribute, BinaryOperator wrapping) { // 不是包装属性 if (!aliasAttribute.isWrapped()) { - processAttribute(syntheticAnnotation, originalAttribute, aliasAttribute, wrapping); + processAttribute(synthesizedAnnotationAggregator, originalAttribute, aliasAttribute, wrapping); return; } // 是包装属性 - final AbstractAnnotationAttributeWrapper wrapper = (AbstractAnnotationAttributeWrapper)aliasAttribute; + final AbstractWrappedAnnotationAttribute wrapper = (AbstractWrappedAnnotationAttribute)aliasAttribute; wrapper.getAllLinkedNonWrappedAttributes().forEach( - t -> processAttribute(syntheticAnnotation, originalAttribute, t, wrapping) + t -> processAttribute(synthesizedAnnotationAggregator, originalAttribute, t, wrapping) ); } @@ -76,10 +76,10 @@ public class AliasForLinkAttributePostProcessor implements SynthesizedAnnotation * 获取指定注解属性,然后将其再进行一层包装 */ private void processAttribute( - SyntheticAnnotation syntheticAnnotation, AnnotationAttribute originalAttribute, + SynthesizedAnnotationAggregator synthesizedAnnotationAggregator, AnnotationAttribute originalAttribute, AnnotationAttribute target, BinaryOperator wrapping) { Opt.ofNullable(target.getAnnotationType()) - .map(syntheticAnnotation::getSynthesizedAnnotation) + .map(synthesizedAnnotationAggregator::getSynthesizedAnnotation) .ifPresent(t -> t.replaceAttribute(target.getAttributeName(), old -> wrapping.apply(old, originalAttribute))); } @@ -87,6 +87,7 @@ public class AliasForLinkAttributePostProcessor implements SynthesizedAnnotation * 检查两个属性是否互为别名 */ private void checkCircularDependency(AnnotationAttribute original, AnnotationAttribute alias) { + SyntheticAnnotationUtil.checkLinkedSelf(original, alias); Link annotation = SyntheticAnnotationUtil.getLink(alias, RelationType.ALIAS_FOR, RelationType.FORCE_ALIAS_FOR); if (ObjectUtil.isNull(annotation)) { return; diff --git a/hutool-core/src/main/java/cn/hutool/core/annotation/AliasedAnnotationAttribute.java b/hutool-core/src/main/java/cn/hutool/core/annotation/AliasedAnnotationAttribute.java index 36d8dda81..53997f0ee 100644 --- a/hutool-core/src/main/java/cn/hutool/core/annotation/AliasedAnnotationAttribute.java +++ b/hutool-core/src/main/java/cn/hutool/core/annotation/AliasedAnnotationAttribute.java @@ -9,7 +9,7 @@ package cn.hutool.core.annotation; * @see RelationType#FORCE_ALIAS_FOR * @see RelationType#ALIAS_FOR */ -public class AliasedAnnotationAttribute extends AbstractAnnotationAttributeWrapper { +public class AliasedAnnotationAttribute extends AbstractWrappedAnnotationAttribute { protected AliasedAnnotationAttribute(AnnotationAttribute origin, AnnotationAttribute linked) { super(origin, linked); diff --git a/hutool-core/src/main/java/cn/hutool/core/annotation/AnnotationAggregator.java b/hutool-core/src/main/java/cn/hutool/core/annotation/AnnotationAggregator.java new file mode 100644 index 000000000..25e15d1cf --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/annotation/AnnotationAggregator.java @@ -0,0 +1,49 @@ +package cn.hutool.core.annotation; + +import java.lang.annotation.Annotation; +import java.lang.reflect.AnnotatedElement; + +/** + * 表示一组被聚合在一起的注解对象 + * + * @author huangchengxing + */ +public interface AnnotationAggregator extends AnnotatedElement { + + /** + * 获取在聚合中存在的指定注解对象 + * + * @param annotationType 注解类型 + * @param 注解类型 + * @return 注解对象 + */ + @Override + T getAnnotation(Class annotationType); + + /** + * 在聚合中是否存在的指定类型注解对象 + * + * @param annotationType 注解类型 + * @return 是否 + */ + @Override + boolean isAnnotationPresent(Class annotationType); + + /** + * 获取聚合中的全部注解对象 + * + * @return 注解对象 + */ + @Override + Annotation[] getAnnotations(); + + /** + * 从聚合中获取指定类型的属性值 + * + * @param attributeName 属性名称 + * @param attributeType 属性类型 + * @return 属性值 + */ + Object getAttribute(String attributeName, Class attributeType); + +} diff --git a/hutool-core/src/main/java/cn/hutool/core/annotation/AnnotationAttribute.java b/hutool-core/src/main/java/cn/hutool/core/annotation/AnnotationAttribute.java index aface5b92..77631b12d 100644 --- a/hutool-core/src/main/java/cn/hutool/core/annotation/AnnotationAttribute.java +++ b/hutool-core/src/main/java/cn/hutool/core/annotation/AnnotationAttribute.java @@ -1,6 +1,5 @@ package cn.hutool.core.annotation; -import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ReflectUtil; import java.lang.annotation.Annotation; @@ -8,7 +7,7 @@ import java.lang.reflect.Method; /** *

表示注解的某个属性,等同于绑定的调用对象的{@link Method}方法。
- * 在{@link SyntheticAnnotation}的解析以及取值过程中, + * 在{@link SynthesizedAnnotationAggregator}的解析以及取值过程中, * 可以通过设置{@link SynthesizedAnnotation}的注解属性, * 从而使得可以从一个注解对象中属性获取另一个注解对象的属性值 * @@ -16,9 +15,9 @@ import java.lang.reflect.Method; * * @author huangchengxing * @see SynthesizedAnnotationPostProcessor - * @see AnnotationAttributeWrapper + * @see WrappedAnnotationAttribute * @see CacheableAnnotationAttribute - * @see AbstractAnnotationAttributeWrapper + * @see AbstractWrappedAnnotationAttribute * @see ForceAliasedAnnotationAttribute * @see AliasedAnnotationAttribute * @see MirroredAnnotationAttribute @@ -71,9 +70,7 @@ public interface AnnotationAttribute { * * @return 该注解属性的值是否等于默认值 */ - default boolean isValueEquivalentToDefaultValue() { - return ObjectUtil.equals(getValue(), getAttribute().getDefaultValue()); - } + boolean isValueEquivalentToDefaultValue(); /** * 获取属性类型 @@ -95,7 +92,7 @@ public interface AnnotationAttribute { } /** - * 当前注解属性是否已经被{@link AnnotationAttributeWrapper}包装 + * 当前注解属性是否已经被{@link WrappedAnnotationAttribute}包装 * * @return boolean */ 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 08c40fcb0..8662caf8b 100755 --- a/hutool-core/src/main/java/cn/hutool/core/annotation/AnnotationUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/annotation/AnnotationUtil.java @@ -3,10 +3,7 @@ package cn.hutool.core.annotation; import cn.hutool.core.annotation.scanner.*; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.exceptions.UtilException; -import cn.hutool.core.lang.Assert; -import cn.hutool.core.lang.Opt; import cn.hutool.core.util.ArrayUtil; -import cn.hutool.core.util.ClassUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ReflectUtil; @@ -15,10 +12,8 @@ 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; /** * 注解工具类
@@ -356,11 +351,11 @@ public class AnnotationUtil { * @param annotationType 注解类 * @param 注解类型 * @return 合成注解 - * @see SyntheticAnnotation + * @see SynthesizedAnnotationAggregator */ public static T getSynthesisAnnotation(Annotation annotation, Class annotationType) { // TODO 缓存合成注解信息,避免重复解析 - return SyntheticAnnotation.of(annotation).syntheticAnnotation(annotationType); + return SynthesizedAnnotationAggregator.of(annotation).synthesize(annotationType); } /** @@ -374,7 +369,7 @@ public class AnnotationUtil { * @param annotationType 注解类 * @param 注解类型 * @return 合成注解 - * @see SyntheticAnnotation + * @see SynthesizedAnnotationAggregator */ public static List getAllSynthesisAnnotations(AnnotatedElement annotatedEle, Class annotationType) { AnnotationScanner[] scanners = new AnnotationScanner[]{ @@ -397,9 +392,13 @@ public class AnnotationUtil { * @param annotationType 注解类 * @param 注解类型 * @return 合成注解 - * @see SyntheticAnnotation + * @see SynthesizedAnnotationAggregator */ public static T getSyntheticAnnotation(AnnotatedElement annotatedEle, Class annotationType) { + T target = annotatedEle.getAnnotation(annotationType); + if (ObjectUtil.isNotNull(target)) { + return target; + } AnnotationScanner[] scanners = new AnnotationScanner[]{ new MetaAnnotationScanner(), new TypeAnnotationScanner(), new MethodAnnotationScanner(), new FieldAnnotationScanner() }; @@ -471,36 +470,4 @@ public class AnnotationUtil { 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; - } } diff --git a/hutool-core/src/main/java/cn/hutool/core/annotation/ForceAliasedAnnotationAttribute.java b/hutool-core/src/main/java/cn/hutool/core/annotation/ForceAliasedAnnotationAttribute.java index 72318ffba..6638bcbd2 100644 --- a/hutool-core/src/main/java/cn/hutool/core/annotation/ForceAliasedAnnotationAttribute.java +++ b/hutool-core/src/main/java/cn/hutool/core/annotation/ForceAliasedAnnotationAttribute.java @@ -10,7 +10,7 @@ package cn.hutool.core.annotation; * @see RelationType#ALIAS_FOR * @see RelationType#FORCE_ALIAS_FOR */ -public class ForceAliasedAnnotationAttribute extends AbstractAnnotationAttributeWrapper { +public class ForceAliasedAnnotationAttribute extends AbstractWrappedAnnotationAttribute { protected ForceAliasedAnnotationAttribute(AnnotationAttribute origin, AnnotationAttribute linked) { super(origin, linked); diff --git a/hutool-core/src/main/java/cn/hutool/core/annotation/Link.java b/hutool-core/src/main/java/cn/hutool/core/annotation/Link.java index cb841fe79..6d1bb3f50 100644 --- a/hutool-core/src/main/java/cn/hutool/core/annotation/Link.java +++ b/hutool-core/src/main/java/cn/hutool/core/annotation/Link.java @@ -4,7 +4,7 @@ import java.lang.annotation.*; /** *

用于在同一注解中,或具有一定关联的不同注解的属性中,表明这些属性之间具有特定的关联关系。 - * 在通过{@link SyntheticAnnotation}获取合成注解后,合成注解获取属性值时会根据该注解进行调整。
+ * 在通过{@link SynthesizedAnnotationAggregator}获取合成注解后,合成注解获取属性值时会根据该注解进行调整。
* *

该注解存在三个字注解:{@link MirrorFor}、{@link ForceAliasFor}或{@link AliasFor}, * 使用三个子注解等同于{@link Link}。但是需要注意的是, @@ -14,7 +14,7 @@ import java.lang.annotation.*; * 注意:该注解的优先级低于{@link Alias} * * @author huangchengxing - * @see SyntheticAnnotation + * @see SynthesizedAnnotationAggregator * @see RelationType * @see AliasFor * @see MirrorFor diff --git a/hutool-core/src/main/java/cn/hutool/core/annotation/MirrorLinkAttributePostProcessor.java b/hutool-core/src/main/java/cn/hutool/core/annotation/MirrorLinkAttributePostProcessor.java index 7c370ff5a..8547b8a9b 100644 --- a/hutool-core/src/main/java/cn/hutool/core/annotation/MirrorLinkAttributePostProcessor.java +++ b/hutool-core/src/main/java/cn/hutool/core/annotation/MirrorLinkAttributePostProcessor.java @@ -20,7 +20,7 @@ public class MirrorLinkAttributePostProcessor implements SynthesizedAnnotationPo } @Override - public void process(SynthesizedAnnotation annotation, SyntheticAnnotation syntheticAnnotation) { + public void process(SynthesizedAnnotation annotation, SynthesizedAnnotationAggregator synthesizedAnnotationAggregator) { Map attributeMap = new HashMap<>(annotation.getAttributes()); attributeMap.forEach((originalAttributeName, originalAttribute) -> { // 跳过已经解析的镜像属性 @@ -35,7 +35,7 @@ public class MirrorLinkAttributePostProcessor implements SynthesizedAnnotationPo } // 获取指定镜像属性所在的注解 - final SynthesizedAnnotation mirrorAnnotation = SyntheticAnnotationUtil.getLinkedAnnotation(link, syntheticAnnotation, annotation.annotationType()); + final SynthesizedAnnotation mirrorAnnotation = SyntheticAnnotationUtil.getLinkedAnnotation(link, synthesizedAnnotationAggregator, annotation.annotationType()); if (ObjectUtil.isNull(mirrorAnnotation)) { return; } @@ -46,7 +46,7 @@ public class MirrorLinkAttributePostProcessor implements SynthesizedAnnotationPo // 包装这一对镜像属性,并替换原注解中的对应属性 final AnnotationAttribute mirroredOriginalAttribute = new MirroredAnnotationAttribute(originalAttribute, mirrorAttribute); - syntheticAnnotation.getSynthesizedAnnotation(originalAttribute.getAnnotationType()) + synthesizedAnnotationAggregator.getSynthesizedAnnotation(originalAttribute.getAnnotationType()) .setAttribute(originalAttributeName, mirroredOriginalAttribute); final AnnotationAttribute mirroredTargetAttribute = new MirroredAnnotationAttribute(mirrorAttribute, originalAttribute); mirrorAnnotation.setAttribute(link.attribute(), mirroredTargetAttribute); @@ -65,6 +65,7 @@ public class MirrorLinkAttributePostProcessor implements SynthesizedAnnotationPo "mirror attribute [{}] of original attribute [{}] must marked by @Link, and also @LinkType.type() must is [{}]", mirror.getAttribute(), original.getAttribute(), RelationType.MIRROR_FOR ); + SyntheticAnnotationUtil.checkLinkedSelf(original, mirror); } } diff --git a/hutool-core/src/main/java/cn/hutool/core/annotation/MirroredAnnotationAttribute.java b/hutool-core/src/main/java/cn/hutool/core/annotation/MirroredAnnotationAttribute.java index 20d2305ce..e8f0f8efd 100644 --- a/hutool-core/src/main/java/cn/hutool/core/annotation/MirroredAnnotationAttribute.java +++ b/hutool-core/src/main/java/cn/hutool/core/annotation/MirroredAnnotationAttribute.java @@ -9,7 +9,7 @@ import cn.hutool.core.lang.Assert; * @see MirrorLinkAttributePostProcessor * @see RelationType#MIRROR_FOR */ -public class MirroredAnnotationAttribute extends AbstractAnnotationAttributeWrapper { +public class MirroredAnnotationAttribute extends AbstractWrappedAnnotationAttribute { public MirroredAnnotationAttribute(AnnotationAttribute origin, AnnotationAttribute linked) { super(origin, linked); diff --git a/hutool-core/src/main/java/cn/hutool/core/annotation/RelationType.java b/hutool-core/src/main/java/cn/hutool/core/annotation/RelationType.java index ee739ae2d..accfd98ac 100644 --- a/hutool-core/src/main/java/cn/hutool/core/annotation/RelationType.java +++ b/hutool-core/src/main/java/cn/hutool/core/annotation/RelationType.java @@ -3,8 +3,8 @@ package cn.hutool.core.annotation; /** *

注解属性的关系类型
* 若将被{@link Link}注解的属性称为“原始属性”,而在{@link Link}注解中指向的注解属性称为“关联属性”, - * 则该枚举用于描述“原始属性”与“关联属性”在{@link SyntheticAnnotation}处理过程中的作用关系。
- * 根据在{@link Link#type()}中指定的关系类型的不同,通过{@link SyntheticAnnotation}合成的注解的属性值也将有所变化。 + * 则该枚举用于描述“原始属性”与“关联属性”在{@link SynthesizedAnnotationAggregator}处理过程中的作用关系。
+ * 根据在{@link Link#type()}中指定的关系类型的不同,通过{@link SynthesizedAnnotationAggregator}合成的注解的属性值也将有所变化。 * *

当一个注解中的所有属性同时具备多种关系时,将依次按下述顺序处理: *

    @@ -15,7 +15,7 @@ package cn.hutool.core.annotation; *
* * @author huangchengxing - * @see SyntheticAnnotation + * @see SynthesizedAnnotationAggregator * @see Link */ public enum RelationType { diff --git a/hutool-core/src/main/java/cn/hutool/core/annotation/SynthesizedAnnotation.java b/hutool-core/src/main/java/cn/hutool/core/annotation/SynthesizedAnnotation.java index fc51eb4d1..2607d94f7 100644 --- a/hutool-core/src/main/java/cn/hutool/core/annotation/SynthesizedAnnotation.java +++ b/hutool-core/src/main/java/cn/hutool/core/annotation/SynthesizedAnnotation.java @@ -7,14 +7,14 @@ import java.util.Map; import java.util.function.UnaryOperator; /** - *

用于在{@link SyntheticAnnotation}中表示一个处于合成状态的注解对象。
+ *

用于在{@link SynthesizedAnnotationAggregator}中表示一个处于合成状态的注解对象。
* 当对多个合成注解排序时,默认先按{@link #getVerticalDistance()}排序, * 再按{@link #getHorizontalDistance()}排序。 * 该顺序应当保证当合成注解与其他注解存在层级关系时, * 离根对象最接近的注解被排在靠前的位置。 * * @author huangchengxing - * @see SyntheticAnnotation + * @see SynthesizedAnnotationAggregator */ public interface SynthesizedAnnotation extends Annotation, Comparable { @@ -23,7 +23,7 @@ public interface SynthesizedAnnotation extends Annotation, Comparable合成注解一般被用于处理类层级结果中具有直接或间接关联的注解对象, * 当实例被创建时,会获取到这些注解对象,并使用{@link SynthesizedAnnotationSelector}对类型相同的注解进行过滤, * 并最终得到类型不重复的有效注解对象。这些有效注解将被包装为{@link SynthesizedAnnotation}, - * 然后最终用于“合成”一个{@link SyntheticAnnotation}。
+ * 然后最终用于“合成”一个{@link SynthesizedAnnotationAggregator}。
* {@link SynthesizedAnnotationSelector}是合成注解生命周期中的第一个钩子, * 自定义选择器以拦截原始注解被扫描的过程。 * @@ -21,7 +21,7 @@ import java.util.Collection; * {@link SynthesizedAnnotationPostProcessor}是合成注解生命周期中的第二个钩子, * 自定义后置处理器以拦截原始在转为待合成注解后的初始化过程。 * - *

合成注解允许通过{@link #syntheticAnnotation(Class)}合成一个指定的注解对象, + *

合成注解允许通过{@link #synthesize(Class)}合成一个指定的注解对象, * 该方法返回的注解对象可能是原始的注解对象,也有可能通过动态代理的方式生成, * 该对象实例的属性不一定来自对象本身,而是来自于经过{@link SynthesizedAnnotationAttributeProcessor} * 处理后的、用于合成当前实例的全部关联注解的相关属性。
@@ -37,9 +37,9 @@ import java.util.Collection; * @see SynthesizedAnnotationSelector * @see SynthesizedAnnotationAttributeProcessor * @see SynthesizedAnnotationPostProcessor - * @see SyntheticMetaAnnotation + * @see SynthesizedMetaAnnotationAggregator */ -public interface SyntheticAnnotation extends Annotation, AnnotatedElement { +public interface SynthesizedAnnotationAggregator extends Annotation, AnnotationAggregator { /** * 获取合成注解选择器 @@ -53,14 +53,14 @@ public interface SyntheticAnnotation extends Annotation, AnnotatedElement { * * @return 合成注解属性处理器 */ - SynthesizedAnnotationAttributeProcessor getAttributeProcessor(); + SynthesizedAnnotationAttributeProcessor getAnnotationAttributeProcessor(); /** * 获取合成注解属性后置处理器 * * @return 合成注解属性后置处理器 */ - Collection getSynthesizedAnnotationAttributePostProcessors(); + Collection getAnnotationAttributePostProcessors(); /** * 获取已合成的注解 @@ -75,7 +75,7 @@ public interface SyntheticAnnotation extends Annotation, AnnotatedElement { * * @return 合成注解 */ - Collection getAllSyntheticAnnotations(); + Collection getAllSynthesizedAnnotation(); /** * 获取当前的注解类型 @@ -87,33 +87,6 @@ public interface SyntheticAnnotation extends Annotation, AnnotatedElement { return this.getClass(); } - /** - * 获取指定注解对象 - * - * @param annotationType 注解类型 - * @param 注解类型 - * @return 注解对象 - */ - @Override - T getAnnotation(Class annotationType); - - /** - * 是否存在指定注解 - * - * @param annotationType 注解类型 - * @return 是否 - */ - @Override - boolean isAnnotationPresent(Class annotationType); - - /** - * 获取全部注解 - * - * @return 注解对象 - */ - @Override - Annotation[] getAnnotations(); - /** * 获取合成注解 * @@ -121,16 +94,7 @@ public interface SyntheticAnnotation extends Annotation, AnnotatedElement { * @param 注解类型 * @return 类型 */ - T syntheticAnnotation(Class annotationType); - - /** - * 获取属性值 - * - * @param attributeName 属性名称 - * @param attributeType 属性类型 - * @return 属性值 - */ - Object getAttribute(String attributeName, Class attributeType); + T synthesize(Class annotationType); /** * 基于指定根注解,构建包括其元注解在内的合成注解 @@ -139,8 +103,8 @@ public interface SyntheticAnnotation extends Annotation, AnnotatedElement { * @param 注解类型 * @return 合成注解 */ - static SyntheticAnnotation of(T rootAnnotation) { - return new SyntheticMetaAnnotation(rootAnnotation); + static SynthesizedAnnotationAggregator of(T rootAnnotation) { + return new SynthesizedMetaAnnotationAggregator(rootAnnotation); } } diff --git a/hutool-core/src/main/java/cn/hutool/core/annotation/SynthesizedAnnotationAttributeProcessor.java b/hutool-core/src/main/java/cn/hutool/core/annotation/SynthesizedAnnotationAttributeProcessor.java index ad0464f5b..cf8b44cc6 100644 --- a/hutool-core/src/main/java/cn/hutool/core/annotation/SynthesizedAnnotationAttributeProcessor.java +++ b/hutool-core/src/main/java/cn/hutool/core/annotation/SynthesizedAnnotationAttributeProcessor.java @@ -3,7 +3,7 @@ package cn.hutool.core.annotation; import java.util.Collection; /** - * 合成注解属性选择器。用于在{@link SyntheticAnnotation}中从指定类型的合成注解里获取到对应的属性值 + * 合成注解属性选择器。用于在{@link SynthesizedAnnotationAggregator}中从指定类型的合成注解里获取到对应的属性值 * * @author huangchengxing */ diff --git a/hutool-core/src/main/java/cn/hutool/core/annotation/SynthesizedAnnotationPostProcessor.java b/hutool-core/src/main/java/cn/hutool/core/annotation/SynthesizedAnnotationPostProcessor.java index 7e5cce1f0..c8028dd46 100644 --- a/hutool-core/src/main/java/cn/hutool/core/annotation/SynthesizedAnnotationPostProcessor.java +++ b/hutool-core/src/main/java/cn/hutool/core/annotation/SynthesizedAnnotationPostProcessor.java @@ -5,7 +5,7 @@ import cn.hutool.core.comparator.CompareUtil; import java.util.Comparator; /** - *

被合成注解后置处理器,用于在{@link SyntheticAnnotation}加载完所有待合成注解后, + *

被合成注解后置处理器,用于在{@link SynthesizedAnnotationAggregator}加载完所有待合成注解后, * 再对加载好的{@link SynthesizedAnnotation}进行后置处理。
* 当多个{@link SynthesizedAnnotationPostProcessor}需要一起执行时,将按照{@link #order()}的返回值进行排序, * 该值更小的处理器将被优先执行。 @@ -49,8 +49,8 @@ public interface SynthesizedAnnotationPostProcessor extends Comparable - * 该接口用于在{@link SyntheticAnnotation}中用于从一批相同的注解对象中筛选最终用于合成注解对象。 + * 该接口用于在{@link SynthesizedAnnotationAggregator}中用于从一批相同的注解对象中筛选最终用于合成注解对象。 * * @author huangchengxing */ diff --git a/hutool-core/src/main/java/cn/hutool/core/annotation/SyntheticMetaAnnotation.java b/hutool-core/src/main/java/cn/hutool/core/annotation/SynthesizedMetaAnnotationAggregator.java similarity index 90% rename from hutool-core/src/main/java/cn/hutool/core/annotation/SyntheticMetaAnnotation.java rename to hutool-core/src/main/java/cn/hutool/core/annotation/SynthesizedMetaAnnotationAggregator.java index 26bc5f73f..98d29088e 100644 --- a/hutool-core/src/main/java/cn/hutool/core/annotation/SyntheticMetaAnnotation.java +++ b/hutool-core/src/main/java/cn/hutool/core/annotation/SynthesizedMetaAnnotationAggregator.java @@ -15,10 +15,10 @@ import java.util.stream.Collectors; import java.util.stream.Stream; /** - * {@link SyntheticAnnotation}的基本实现,表示一个根注解与根注解上的多层元注解合成的注解 + * {@link SynthesizedAnnotationAggregator}的基本实现,表示一个根注解与根注解上的多层元注解的聚合状态 * *

假设现有注解A,A上存在元注解B,B上存在元注解C,则对注解A进行解析, - * 将得到包含根注解A,以及其元注解B、C在内的合成元注解{@link SyntheticMetaAnnotation}。 + * 将得到包含根注解A,以及其元注解B、C在内的合成元注解聚合{@link SynthesizedMetaAnnotationAggregator}。 * 从{@link AnnotatedElement}的角度来说,得到的合成注解是一个同时承载有ABC三个注解对象的被注解元素, * 因此通过调用{@link AnnotatedElement}的相关方法将返回对应符合语义的注解对象。 * @@ -39,8 +39,8 @@ import java.util.stream.Stream; * * 若用户需要自行扩展,则需要保证上述三个处理器被正确注入当前实例。 * - *

{@link SyntheticMetaAnnotation}支持通过{@link #getAttribute(String, Class)}, - * 或通过{@link #syntheticAnnotation(Class)}获得注解代理对象后获取指定类型的注解属性值, + *

{@link SynthesizedMetaAnnotationAggregator}支持通过{@link #getAttribute(String, Class)}, + * 或通过{@link #synthesize(Class)}获得注解代理对象后获取指定类型的注解属性值, * 返回的属性值将根据合成注解中对应原始注解属性上的{@link Alias}与{@link Link}注解而有所变化。 * 通过当前实例获取属性值时,将经过{@link SynthesizedAnnotationAttributeProcessor}的处理。
* 默认情况下,实例将会注册{@link CacheableSynthesizedAnnotationAttributeProcessor}, @@ -50,7 +50,7 @@ import java.util.stream.Stream; * @see AnnotationUtil * @see SynthesizedAnnotationSelector */ -public class SyntheticMetaAnnotation implements SyntheticAnnotation { +public class SynthesizedMetaAnnotationAggregator implements SynthesizedAnnotationAggregator { /** * 根注解,即当前查找的注解 @@ -84,7 +84,7 @@ public class SyntheticMetaAnnotation implements SyntheticAnnotation { * * @param source 源注解 */ - public SyntheticMetaAnnotation(Annotation source) { + public SynthesizedMetaAnnotationAggregator(Annotation source) { this( source, SynthesizedAnnotationSelector.NEAREST_AND_OLDEST_PRIORITY, new CacheableSynthesizedAnnotationAttributeProcessor(), @@ -103,7 +103,7 @@ public class SyntheticMetaAnnotation implements SyntheticAnnotation { * @param annotationSelector 合成注解选择器 * @param attributeProcessor 注解属性处理器 */ - public SyntheticMetaAnnotation( + public SynthesizedMetaAnnotationAggregator( Annotation annotation, SynthesizedAnnotationSelector annotationSelector, SynthesizedAnnotationAttributeProcessor attributeProcessor, @@ -137,15 +137,6 @@ public class SyntheticMetaAnnotation implements SyntheticAnnotation { return source; } - /** - * 获取已解析的元注解信息 - * - * @return 已解析的元注解信息 - */ - Map, SynthesizedAnnotation> getMetaAnnotationMap() { - return metaAnnotationMap; - } - /** * 获取合成注解选择器 * @@ -162,7 +153,7 @@ public class SyntheticMetaAnnotation implements SyntheticAnnotation { * @return 合成注解属性处理器 */ @Override - public SynthesizedAnnotationAttributeProcessor getAttributeProcessor() { + public SynthesizedAnnotationAttributeProcessor getAnnotationAttributeProcessor() { return this.attributeProcessor; } @@ -172,7 +163,7 @@ public class SyntheticMetaAnnotation implements SyntheticAnnotation { * @return 合成注解属性后置处理器 */ @Override - public Collection getSynthesizedAnnotationAttributePostProcessors() { + public Collection getAnnotationAttributePostProcessors() { return this.postProcessors; } @@ -193,7 +184,7 @@ public class SyntheticMetaAnnotation implements SyntheticAnnotation { * @return 合成注解 */ @Override - public Collection getAllSyntheticAnnotations() { + public Collection getAllSynthesizedAnnotation() { return metaAnnotationMap.values(); } @@ -254,10 +245,10 @@ public class SyntheticMetaAnnotation implements SyntheticAnnotation { * * @param annotationType 注解类型 * @return 合成注解对象 - * @see SyntheticAnnotationProxy#create(Class, SyntheticAnnotation) + * @see SyntheticAnnotationProxy#create(Class, SynthesizedAnnotationAggregator) */ @Override - public T syntheticAnnotation(Class annotationType) { + public T synthesize(Class annotationType) { return SyntheticAnnotationProxy.create(annotationType, this); } @@ -299,14 +290,14 @@ public class SyntheticMetaAnnotation implements SyntheticAnnotation { */ public static class MetaAnnotation implements Annotation, SynthesizedAnnotation { - private final SyntheticAnnotation owner; + private final SynthesizedAnnotationAggregator owner; private final Annotation root; private final Annotation annotation; private final Map attributeMethodCaches; private final int verticalDistance; private final int horizontalDistance; - public MetaAnnotation(SyntheticAnnotation owner, Annotation root, Annotation annotation, int verticalDistance, int horizontalDistance) { + public MetaAnnotation(SynthesizedAnnotationAggregator owner, Annotation root, Annotation annotation, int verticalDistance, int horizontalDistance) { this.owner = owner; this.root = root; this.annotation = annotation; @@ -323,7 +314,7 @@ public class SyntheticMetaAnnotation implements SyntheticAnnotation { * @return 合成注解 */ @Override - public SyntheticAnnotation getOwner() { + public SynthesizedAnnotationAggregator getOwner() { return owner; } diff --git a/hutool-core/src/main/java/cn/hutool/core/annotation/SyntheticAnnotationProxy.java b/hutool-core/src/main/java/cn/hutool/core/annotation/SyntheticAnnotationProxy.java index e71208c8a..8a8688944 100644 --- a/hutool-core/src/main/java/cn/hutool/core/annotation/SyntheticAnnotationProxy.java +++ b/hutool-core/src/main/java/cn/hutool/core/annotation/SyntheticAnnotationProxy.java @@ -38,18 +38,18 @@ class SyntheticAnnotationProxy implements InvocationHandler { /** * 创建一个代理注解,生成的代理对象将是{@link SyntheticProxyAnnotation}与指定的注解类的子类。 *

    - *
  • 当作为{@code annotationType}所指定的类型使用时,其属性将通过合成它的{@link SyntheticAnnotation}获取;
  • + *
  • 当作为{@code annotationType}所指定的类型使用时,其属性将通过合成它的{@link SynthesizedAnnotationAggregator}获取;
  • *
  • 当作为{@link SyntheticProxyAnnotation}或{@link SynthesizedAnnotation}使用时,将可以获得原始注解实例的相关信息;
  • *
* * @param annotationType 注解类型 - * @param syntheticAnnotation 合成注解 + * @param synthesizedAnnotationAggregator 合成注解 * @return 代理注解 */ @SuppressWarnings("unchecked") static T create( - Class annotationType, SyntheticAnnotation syntheticAnnotation) { - final SynthesizedAnnotation annotation = syntheticAnnotation.getSynthesizedAnnotation(annotationType); + Class annotationType, SynthesizedAnnotationAggregator synthesizedAnnotationAggregator) { + final SynthesizedAnnotation annotation = synthesizedAnnotationAggregator.getSynthesizedAnnotation(annotationType); if (ObjectUtil.isNull(annotation)) { return null; } @@ -83,7 +83,6 @@ class SyntheticAnnotationProxy implements InvocationHandler { methods.put("getSyntheticAnnotation", (method, args) -> proxyGetSyntheticAnnotation()); methods.put("getSynthesizedAnnotation", (method, args) -> proxyGetSynthesizedAnnotation()); methods.put("getRoot", (method, args) -> annotation.getRoot()); - methods.put("isRoot", (method, args) -> annotation.isRoot()); methods.put("getVerticalDistance", (method, args) -> annotation.getVerticalDistance()); methods.put("getHorizontalDistance", (method, args) -> annotation.getHorizontalDistance()); methods.put("hasAttribute", (method, args) -> annotation.hasAttribute((String)args[0], (Class)args[1])); @@ -135,7 +134,7 @@ class SyntheticAnnotationProxy implements InvocationHandler { * * @return 合成注解 */ - SyntheticAnnotation getSyntheticAnnotation(); + SynthesizedAnnotationAggregator getSyntheticAnnotation(); /** * 获取该代理注解对应的已合成注解 diff --git a/hutool-core/src/main/java/cn/hutool/core/annotation/SyntheticAnnotationUtil.java b/hutool-core/src/main/java/cn/hutool/core/annotation/SyntheticAnnotationUtil.java index 71746cdf1..dc054c90f 100644 --- a/hutool-core/src/main/java/cn/hutool/core/annotation/SyntheticAnnotationUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/annotation/SyntheticAnnotationUtil.java @@ -9,7 +9,7 @@ import java.lang.annotation.Annotation; import java.util.Comparator; /** - * {@link SyntheticAnnotation}相关工具,用于内部使用 + * {@link SynthesizedAnnotationAggregator}相关工具,用于内部使用 * * @author huangchengxing */ @@ -33,12 +33,12 @@ class SyntheticAnnotationUtil { * 从合成注解中获取{@link Link#type()}指定的注解对象 * * @param annotation {@link Link}注解 - * @param syntheticAnnotation 合成注解 + * @param synthesizedAnnotationAggregator 合成注解 */ static SynthesizedAnnotation getLinkedAnnotation( - Link annotation, SyntheticAnnotation syntheticAnnotation, Class defaultType) { + Link annotation, SynthesizedAnnotationAggregator synthesizedAnnotationAggregator, Class defaultType) { final Class targetAnnotationType = getLinkedAnnotationType(annotation, defaultType); - return syntheticAnnotation.getSynthesizedAnnotation(targetAnnotationType); + return synthesizedAnnotationAggregator.getSynthesizedAnnotation(targetAnnotationType); } /** @@ -68,6 +68,17 @@ class SyntheticAnnotationUtil { ); } + /** + * 检查{@link Link}指向的注解属性是否就是本身 + * + * @param original {@link Link}注解的属性 + * @param linked {@link Link}指向的注解属性 + */ + static void checkLinkedSelf(AnnotationAttribute original, AnnotationAttribute linked) { + boolean linkSelf = (original == linked) || ObjectUtil.equals(original.getAttribute(), linked.getAttribute()); + Assert.isFalse(linkSelf, "cannot link self [{}]", original.getAttribute()); + } + /** * 检查{@link Link}指向的注解属性是否存在 * diff --git a/hutool-core/src/main/java/cn/hutool/core/annotation/AnnotationAttributeWrapper.java b/hutool-core/src/main/java/cn/hutool/core/annotation/WrappedAnnotationAttribute.java similarity index 92% rename from hutool-core/src/main/java/cn/hutool/core/annotation/AnnotationAttributeWrapper.java rename to hutool-core/src/main/java/cn/hutool/core/annotation/WrappedAnnotationAttribute.java index 54caa5d98..6ca5a3f52 100644 --- a/hutool-core/src/main/java/cn/hutool/core/annotation/AnnotationAttributeWrapper.java +++ b/hutool-core/src/main/java/cn/hutool/core/annotation/WrappedAnnotationAttribute.java @@ -27,7 +27,7 @@ import java.util.Collection; * @see AliasedAnnotationAttribute * @see MirroredAnnotationAttribute */ -public interface AnnotationAttributeWrapper extends AnnotationAttribute { +public interface WrappedAnnotationAttribute extends AnnotationAttribute { // =========================== 新增方法 =========================== @@ -89,9 +89,7 @@ public interface AnnotationAttributeWrapper extends AnnotationAttribute { * @return 该注解属性的值是否等于默认值 */ @Override - default boolean isValueEquivalentToDefaultValue() { - return getOriginal().isValueEquivalentToDefaultValue() && getLinked().isValueEquivalentToDefaultValue(); - } + boolean isValueEquivalentToDefaultValue(); /** * 获取属性类型 @@ -115,7 +113,7 @@ public interface AnnotationAttributeWrapper extends AnnotationAttribute { } /** - * 当前注解属性是否已经被{@link AnnotationAttributeWrapper}包装 + * 当前注解属性是否已经被{@link WrappedAnnotationAttribute}包装 * * @return boolean */ diff --git a/hutool-core/src/test/java/cn/hutool/core/annotation/AbstractAnnotationAttributeWrapperTest.java b/hutool-core/src/test/java/cn/hutool/core/annotation/AbstractWrappedAnnotationAttributeTest.java similarity index 81% rename from hutool-core/src/test/java/cn/hutool/core/annotation/AbstractAnnotationAttributeWrapperTest.java rename to hutool-core/src/test/java/cn/hutool/core/annotation/AbstractWrappedAnnotationAttributeTest.java index b828ab888..66059a18d 100644 --- a/hutool-core/src/test/java/cn/hutool/core/annotation/AbstractAnnotationAttributeWrapperTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/annotation/AbstractWrappedAnnotationAttributeTest.java @@ -8,7 +8,7 @@ import org.junit.Test; import java.lang.annotation.*; import java.lang.reflect.Method; -public class AbstractAnnotationAttributeWrapperTest { +public class AbstractWrappedAnnotationAttributeTest { @Test public void workTest() { @@ -17,7 +17,9 @@ public class AbstractAnnotationAttributeWrapperTest { CacheableAnnotationAttribute valueAttribute = new CacheableAnnotationAttribute(annotation, valueMethod); Method nameMethod = ReflectUtil.getMethod(AnnotationForTest1.class, "name1"); CacheableAnnotationAttribute nameAttribute = new CacheableAnnotationAttribute(annotation, nameMethod); - TestAnnotationAttributeWrapper nameWrapper = new TestAnnotationAttributeWrapper(nameAttribute, valueAttribute); + AbstractWrappedAnnotationAttribute nameWrapper = new TestWrappedAnnotationAttribute(nameAttribute, valueAttribute); + + Assert.assertEquals(nameWrapper.getAnnotation(), annotation); // 注解属性 Assert.assertEquals(annotation, nameWrapper.getAnnotation()); @@ -40,7 +42,7 @@ public class AbstractAnnotationAttributeWrapperTest { CacheableAnnotationAttribute value1Attribute = new CacheableAnnotationAttribute(annotation1, value1Method); Method name1Method = ReflectUtil.getMethod(AnnotationForTest1.class, "name1"); CacheableAnnotationAttribute name1Attribute = new CacheableAnnotationAttribute(annotation1, name1Method); - TestAnnotationAttributeWrapper wrapper1 = new TestAnnotationAttributeWrapper(name1Attribute, value1Attribute); + AbstractWrappedAnnotationAttribute wrapper1 = new TestWrappedAnnotationAttribute(name1Attribute, value1Attribute); Assert.assertEquals(name1Attribute, wrapper1.getNonWrappedOriginal()); Assert.assertEquals(CollUtil.newArrayList(name1Attribute, value1Attribute), wrapper1.getAllLinkedNonWrappedAttributes()); @@ -48,7 +50,7 @@ public class AbstractAnnotationAttributeWrapperTest { Annotation annotation2 = ClassForTest1.class.getAnnotation(AnnotationForTest2.class); Method value2Method = ReflectUtil.getMethod(AnnotationForTest2.class, "value2"); CacheableAnnotationAttribute value2Attribute = new CacheableAnnotationAttribute(annotation2, value2Method); - TestAnnotationAttributeWrapper wrapper2 = new TestAnnotationAttributeWrapper(wrapper1, value2Attribute); + AbstractWrappedAnnotationAttribute wrapper2 = new TestWrappedAnnotationAttribute(wrapper1, value2Attribute); Assert.assertEquals(name1Attribute, wrapper2.getNonWrappedOriginal()); Assert.assertEquals(CollUtil.newArrayList(name1Attribute, value1Attribute, value2Attribute), wrapper2.getAllLinkedNonWrappedAttributes()); @@ -56,20 +58,25 @@ public class AbstractAnnotationAttributeWrapperTest { Annotation annotation3 = ClassForTest1.class.getAnnotation(AnnotationForTest3.class); Method value3Method = ReflectUtil.getMethod(AnnotationForTest3.class, "value3"); CacheableAnnotationAttribute value3Attribute = new CacheableAnnotationAttribute(annotation3, value3Method); - TestAnnotationAttributeWrapper wrapper3 = new TestAnnotationAttributeWrapper(value3Attribute, wrapper2); + AbstractWrappedAnnotationAttribute wrapper3 = new TestWrappedAnnotationAttribute(value3Attribute, wrapper2); Assert.assertEquals(value3Attribute, wrapper3.getNonWrappedOriginal()); Assert.assertEquals(CollUtil.newArrayList(value3Attribute, name1Attribute, value1Attribute, value2Attribute), wrapper3.getAllLinkedNonWrappedAttributes()); } - static class TestAnnotationAttributeWrapper extends AbstractAnnotationAttributeWrapper { - protected TestAnnotationAttributeWrapper(AnnotationAttribute original, AnnotationAttribute linked) { + static class TestWrappedAnnotationAttribute extends AbstractWrappedAnnotationAttribute { + protected TestWrappedAnnotationAttribute(AnnotationAttribute original, AnnotationAttribute linked) { super(original, linked); } @Override public Object getValue() { return linked.getValue(); } + + @Override + public boolean isValueEquivalentToDefaultValue() { + return getOriginal().isValueEquivalentToDefaultValue() && getLinked().isValueEquivalentToDefaultValue(); + } } @Retention(RetentionPolicy.RUNTIME) diff --git a/hutool-core/src/test/java/cn/hutool/core/annotation/AliasAttributePostProcessorTest.java b/hutool-core/src/test/java/cn/hutool/core/annotation/AliasAttributePostProcessorTest.java new file mode 100644 index 000000000..f7ad67e8b --- /dev/null +++ b/hutool-core/src/test/java/cn/hutool/core/annotation/AliasAttributePostProcessorTest.java @@ -0,0 +1,190 @@ +package cn.hutool.core.annotation; + +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.ReflectUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.lang.annotation.*; +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.function.UnaryOperator; + +public class AliasAttributePostProcessorTest { + + @Test + public void processTest() { + AliasAttributePostProcessor processor = new AliasAttributePostProcessor(); + + Map, SynthesizedAnnotation> annotationMap = new HashMap<>(); + SynthesizedAnnotationAggregator synthesizedAnnotationAggregator = new TestSynthesizedAnnotationAggregator(annotationMap); + AnnotationForTest annotation = ClassForTest.class.getAnnotation(AnnotationForTest.class); + SynthesizedAnnotation synthesizedAnnotation = new TestSynthesizedAnnotation(synthesizedAnnotationAggregator, annotation); + annotationMap.put(annotation.annotationType(), synthesizedAnnotation); + + processor.process(synthesizedAnnotation, synthesizedAnnotationAggregator); + AnnotationAttribute valueAttribute = synthesizedAnnotation.getAttributes().get("value"); + Assert.assertEquals(ReflectUtil.getMethod(AnnotationForTest.class, "value"), valueAttribute.getAttribute()); + Assert.assertTrue(valueAttribute.isWrapped()); + Assert.assertEquals(ForceAliasedAnnotationAttribute.class, valueAttribute.getClass()); + + AnnotationAttribute nameAttribute = synthesizedAnnotation.getAttributes().get("name"); + Assert.assertEquals(ReflectUtil.getMethod(AnnotationForTest.class, "name"), nameAttribute.getAttribute()); + Assert.assertFalse(nameAttribute.isWrapped()); + Assert.assertEquals(CacheableAnnotationAttribute.class, nameAttribute.getClass()); + + Assert.assertEquals(nameAttribute, ((WrappedAnnotationAttribute)valueAttribute).getLinked()); + } + + @AnnotationForTest + static class ClassForTest {} + + @Retention(RetentionPolicy.RUNTIME) + @Target({ ElementType.METHOD, ElementType.TYPE }) + @interface AnnotationForTest { + @Alias("name") + String value() default ""; + String name() default ""; + } + + static class TestSynthesizedAnnotationAggregator implements SynthesizedAnnotationAggregator { + + private final Map, SynthesizedAnnotation> annotationMap; + + public TestSynthesizedAnnotationAggregator(Map, SynthesizedAnnotation> annotationMap) { + this.annotationMap = annotationMap; + } + + @Override + public SynthesizedAnnotationSelector getAnnotationSelector() { + return null; + } + + @Override + public SynthesizedAnnotationAttributeProcessor getAnnotationAttributeProcessor() { + return null; + } + + @Override + public Collection getAnnotationAttributePostProcessors() { + return null; + } + + @Override + public SynthesizedAnnotation getSynthesizedAnnotation(Class annotationType) { + return annotationMap.get(annotationType); + } + + @Override + public Collection getAllSynthesizedAnnotation() { + return null; + } + + @Override + public T getAnnotation(Class annotationType) { + return null; + } + + @Override + public boolean isAnnotationPresent(Class annotationType) { + return false; + } + + @Override + public Annotation[] getAnnotations() { + return new Annotation[0]; + } + + @Override + public T synthesize(Class annotationType) { + return null; + } + + @Override + public Object getAttribute(String attributeName, Class attributeType) { + return null; + } + + @Override + public Annotation[] getDeclaredAnnotations() { + return new Annotation[0]; + } + } + + static class TestSynthesizedAnnotation implements SynthesizedAnnotation { + + private final Annotation annotation; + private final SynthesizedAnnotationAggregator owner; + private final Map attributeMap; + + public TestSynthesizedAnnotation(SynthesizedAnnotationAggregator owner, Annotation annotation) { + this.owner = owner; + this.attributeMap = new HashMap<>(); + this.annotation = annotation; + for (Method declaredMethod : annotation.annotationType().getDeclaredMethods()) { + attributeMap.put(declaredMethod.getName(), new CacheableAnnotationAttribute(annotation, declaredMethod)); + } + } + + @Override + public SynthesizedAnnotationAggregator getOwner() { + return owner; + } + + @Override + public Object getRoot() { + return null; + } + + @Override + public Annotation getAnnotation() { + return annotation; + } + + @Override + public int getVerticalDistance() { + return 0; + } + + @Override + public int getHorizontalDistance() { + return 0; + } + + @Override + public boolean hasAttribute(String attributeName, Class returnType) { + return false; + } + + @Override + public Map getAttributes() { + return attributeMap; + } + + @Override + public void setAttribute(String attributeName, AnnotationAttribute attribute) { + attributeMap.put(attributeName, attribute); + } + + @Override + public void replaceAttribute(String attributeName, UnaryOperator operator) { + AnnotationAttribute annotationAttribute = attributeMap.get(attributeName); + if (ObjectUtil.isNotNull(annotationAttribute)) { + attributeMap.put(attributeName, operator.apply(annotationAttribute)); + } + } + + @Override + public Object getAttributeValue(String attributeName) { + return null; + } + + @Override + public Class annotationType() { + return annotation.annotationType(); + } + } + +} diff --git a/hutool-core/src/test/java/cn/hutool/core/annotation/AliasForLinkAttributePostProcessorTest.java b/hutool-core/src/test/java/cn/hutool/core/annotation/AliasForLinkAttributePostProcessorTest.java new file mode 100644 index 000000000..5d0c4ad37 --- /dev/null +++ b/hutool-core/src/test/java/cn/hutool/core/annotation/AliasForLinkAttributePostProcessorTest.java @@ -0,0 +1,218 @@ +package cn.hutool.core.annotation; + +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.ReflectUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.lang.annotation.*; +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.function.UnaryOperator; + +public class AliasForLinkAttributePostProcessorTest { + + @Test + public void processForceAliasForTest() { + AliasForLinkAttributePostProcessor processor = new AliasForLinkAttributePostProcessor(); + + Map, SynthesizedAnnotation> annotationMap = new HashMap<>(); + SynthesizedAnnotationAggregator synthesizedAnnotationAggregator = new TestSynthesizedAnnotationAggregator(annotationMap); + AnnotationForTest annotation = ClassForTest.class.getAnnotation(AnnotationForTest.class); + SynthesizedAnnotation synthesizedAnnotation = new TestSynthesizedAnnotation(synthesizedAnnotationAggregator, annotation); + annotationMap.put(annotation.annotationType(), synthesizedAnnotation); + + processor.process(synthesizedAnnotation, synthesizedAnnotationAggregator); + AnnotationAttribute valueAttribute = synthesizedAnnotation.getAttributes().get("value"); + Assert.assertEquals(ReflectUtil.getMethod(AnnotationForTest.class, "value"), valueAttribute.getAttribute()); + Assert.assertFalse(valueAttribute.isWrapped()); + Assert.assertEquals(CacheableAnnotationAttribute.class, valueAttribute.getClass()); + + AnnotationAttribute nameAttribute = synthesizedAnnotation.getAttributes().get("name"); + Assert.assertEquals(ReflectUtil.getMethod(AnnotationForTest.class, "name"), nameAttribute.getAttribute()); + Assert.assertTrue(nameAttribute.isWrapped()); + Assert.assertEquals(ForceAliasedAnnotationAttribute.class, nameAttribute.getClass()); + + Assert.assertEquals(valueAttribute, ((WrappedAnnotationAttribute)nameAttribute).getLinked()); + } + + @Test + public void processAliasForTest() { + AliasForLinkAttributePostProcessor processor = new AliasForLinkAttributePostProcessor(); + + Map, SynthesizedAnnotation> annotationMap = new HashMap<>(); + SynthesizedAnnotationAggregator synthesizedAnnotationAggregator = new TestSynthesizedAnnotationAggregator(annotationMap); + AnnotationForTest annotation = ClassForTest.class.getAnnotation(AnnotationForTest.class); + SynthesizedAnnotation synthesizedAnnotation = new TestSynthesizedAnnotation(synthesizedAnnotationAggregator, annotation); + annotationMap.put(annotation.annotationType(), synthesizedAnnotation); + + processor.process(synthesizedAnnotation, synthesizedAnnotationAggregator); + AnnotationAttribute valueAttribute = synthesizedAnnotation.getAttributes().get("value2"); + Assert.assertEquals(ReflectUtil.getMethod(AnnotationForTest.class, "value2"), valueAttribute.getAttribute()); + Assert.assertFalse(valueAttribute.isWrapped()); + Assert.assertEquals(CacheableAnnotationAttribute.class, valueAttribute.getClass()); + + AnnotationAttribute nameAttribute = synthesizedAnnotation.getAttributes().get("name2"); + Assert.assertEquals(ReflectUtil.getMethod(AnnotationForTest.class, "name2"), nameAttribute.getAttribute()); + Assert.assertTrue(nameAttribute.isWrapped()); + Assert.assertEquals(AliasedAnnotationAttribute.class, nameAttribute.getClass()); + + Assert.assertEquals(valueAttribute, ((WrappedAnnotationAttribute)nameAttribute).getLinked()); + } + + @AnnotationForTest + static class ClassForTest {} + + @Retention(RetentionPolicy.RUNTIME) + @Target({ ElementType.METHOD, ElementType.TYPE }) + @interface AnnotationForTest { + @Link(attribute = "name", type = RelationType.FORCE_ALIAS_FOR) + String value() default ""; + String name() default ""; + + @Link(attribute = "name2", type = RelationType.ALIAS_FOR) + String value2() default ""; + String name2() default ""; + } + + static class TestSynthesizedAnnotationAggregator implements SynthesizedAnnotationAggregator { + + private final Map, SynthesizedAnnotation> annotationMap; + + public TestSynthesizedAnnotationAggregator(Map, SynthesizedAnnotation> annotationMap) { + this.annotationMap = annotationMap; + } + + @Override + public SynthesizedAnnotationSelector getAnnotationSelector() { + return null; + } + + @Override + public SynthesizedAnnotationAttributeProcessor getAnnotationAttributeProcessor() { + return null; + } + + @Override + public Collection getAnnotationAttributePostProcessors() { + return null; + } + + @Override + public SynthesizedAnnotation getSynthesizedAnnotation(Class annotationType) { + return annotationMap.get(annotationType); + } + + @Override + public Collection getAllSynthesizedAnnotation() { + return null; + } + + @Override + public T getAnnotation(Class annotationType) { + return null; + } + + @Override + public boolean isAnnotationPresent(Class annotationType) { + return false; + } + + @Override + public Annotation[] getAnnotations() { + return new Annotation[0]; + } + + @Override + public T synthesize(Class annotationType) { + return null; + } + + @Override + public Object getAttribute(String attributeName, Class attributeType) { + return null; + } + + @Override + public Annotation[] getDeclaredAnnotations() { + return new Annotation[0]; + } + } + + static class TestSynthesizedAnnotation implements SynthesizedAnnotation { + + private final Annotation annotation; + private final SynthesizedAnnotationAggregator owner; + private final Map attributeMap; + + public TestSynthesizedAnnotation(SynthesizedAnnotationAggregator owner, Annotation annotation) { + this.owner = owner; + this.attributeMap = new HashMap<>(); + this.annotation = annotation; + for (Method declaredMethod : annotation.annotationType().getDeclaredMethods()) { + attributeMap.put(declaredMethod.getName(), new CacheableAnnotationAttribute(annotation, declaredMethod)); + } + } + + @Override + public SynthesizedAnnotationAggregator getOwner() { + return owner; + } + + @Override + public Object getRoot() { + return null; + } + + @Override + public Annotation getAnnotation() { + return annotation; + } + + @Override + public int getVerticalDistance() { + return 0; + } + + @Override + public int getHorizontalDistance() { + return 0; + } + + @Override + public boolean hasAttribute(String attributeName, Class returnType) { + return false; + } + + @Override + public Map getAttributes() { + return attributeMap; + } + + @Override + public void setAttribute(String attributeName, AnnotationAttribute attribute) { + attributeMap.put(attributeName, attribute); + } + + @Override + public void replaceAttribute(String attributeName, UnaryOperator operator) { + AnnotationAttribute annotationAttribute = attributeMap.get(attributeName); + if (ObjectUtil.isNotNull(annotationAttribute)) { + attributeMap.put(attributeName, operator.apply(annotationAttribute)); + } + } + + @Override + public Object getAttributeValue(String attributeName) { + return null; + } + + @Override + public Class annotationType() { + return annotation.annotationType(); + } + } + +} diff --git a/hutool-core/src/test/java/cn/hutool/core/annotation/AliasedAnnotationAttributeTest.java b/hutool-core/src/test/java/cn/hutool/core/annotation/AliasedAnnotationAttributeTest.java index 4d9d17a45..8c0bc8cbc 100644 --- a/hutool-core/src/test/java/cn/hutool/core/annotation/AliasedAnnotationAttributeTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/annotation/AliasedAnnotationAttributeTest.java @@ -17,15 +17,16 @@ public class AliasedAnnotationAttributeTest { final CacheableAnnotationAttribute valueAttribute = new CacheableAnnotationAttribute(annotation, valueMethod); final Method nameMethod = ReflectUtil.getMethod(AnnotationForTest.class, "name"); final CacheableAnnotationAttribute nameAttribute = new CacheableAnnotationAttribute(annotation, nameMethod); - final AliasedAnnotationAttribute annotationAttribute = new AliasedAnnotationAttribute(valueAttribute, nameAttribute); + final AliasedAnnotationAttribute valueAnnotationAttribute = new AliasedAnnotationAttribute(valueAttribute, nameAttribute); // 注解属性 - Assert.assertEquals(annotation, annotationAttribute.getAnnotation()); - Assert.assertEquals(annotation.annotationType(), annotationAttribute.getAnnotationType()); + Assert.assertEquals(annotation, valueAnnotationAttribute.getAnnotation()); + Assert.assertEquals(annotation.annotationType(), valueAnnotationAttribute.getAnnotationType()); // 方法属性 - Assert.assertEquals(valueMethod.getName(), annotationAttribute.getAttributeName()); - Assert.assertEquals(nameMethod.getReturnType(), annotationAttribute.getAttributeType()); + Assert.assertEquals(valueMethod.getAnnotation(Alias.class), valueAnnotationAttribute.getAnnotation(Alias.class)); + Assert.assertEquals(valueMethod.getName(), valueAnnotationAttribute.getAttributeName()); + Assert.assertEquals(nameMethod.getReturnType(), valueAnnotationAttribute.getAttributeType()); } @Test @@ -63,6 +64,7 @@ public class AliasedAnnotationAttributeTest { @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.METHOD, ElementType.TYPE }) @interface AnnotationForTest { + @Alias("value") String value() default ""; String name() default ""; } diff --git a/hutool-core/src/test/java/cn/hutool/core/annotation/CacheableSynthesizedAnnotationAttributeProcessorTest.java b/hutool-core/src/test/java/cn/hutool/core/annotation/CacheableSynthesizedAnnotationAttributeProcessorTest.java new file mode 100644 index 000000000..c4db00adf --- /dev/null +++ b/hutool-core/src/test/java/cn/hutool/core/annotation/CacheableSynthesizedAnnotationAttributeProcessorTest.java @@ -0,0 +1,100 @@ +package cn.hutool.core.annotation; + +import cn.hutool.core.lang.Opt; +import cn.hutool.core.map.MapBuilder; +import cn.hutool.core.util.ClassUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.lang.annotation.Annotation; +import java.util.Arrays; +import java.util.Map; +import java.util.function.UnaryOperator; + +public class CacheableSynthesizedAnnotationAttributeProcessorTest { + + @Test + public void getAttributeValueTest() { + CacheableSynthesizedAnnotationAttributeProcessor processor = new CacheableSynthesizedAnnotationAttributeProcessor(); + + Map values1 = MapBuilder. create().put("name", "name1").put("value", 111).build(); + SynthesizedAnnotation annotation1 = new TestSynthesizedAnnotation(1, 0, values1); + Map values2 = MapBuilder. create().put("name", "name2").put("value", "value2").build(); + SynthesizedAnnotation annotation2 = new TestSynthesizedAnnotation(0, 0, values2); + + Assert.assertEquals("name2", processor.getAttributeValue("name", String.class, Arrays.asList(annotation1, annotation2))); + Assert.assertEquals(Integer.valueOf(111), processor.getAttributeValue("value", Integer.class, Arrays.asList(annotation1, annotation2))); + } + + static class TestSynthesizedAnnotation implements SynthesizedAnnotation { + + private final int verticalDistance; + private final int horizontalDistance; + private final Map value; + + public TestSynthesizedAnnotation(int verticalDistance, int horizontalDistance, Map value) { + this.verticalDistance = verticalDistance; + this.horizontalDistance = horizontalDistance; + this.value = value; + } + + @Override + public SynthesizedAnnotationAggregator getOwner() { + return null; + } + + @Override + public Object getRoot() { + return null; + } + + @Override + public Annotation getAnnotation() { + return null; + } + + @Override + public int getVerticalDistance() { + return verticalDistance; + } + + @Override + public int getHorizontalDistance() { + return horizontalDistance; + } + + @Override + public boolean hasAttribute(String attributeName, Class returnType) { + return Opt.ofNullable(value.get(attributeName)) + .map(t -> ClassUtil.isAssignable(returnType, t.getClass())) + .orElse(false); + } + + @Override + public Map getAttributes() { + return null; + } + + @Override + public void setAttribute(String attributeName, AnnotationAttribute attribute) { + + } + + @Override + public void replaceAttribute(String attributeName, UnaryOperator operator) { + + } + + @Override + public Object getAttributeValue(String attributeName) { + return value.get(attributeName); + } + + @Override + public Class annotationType() { + return null; + } + + } + +} diff --git a/hutool-core/src/test/java/cn/hutool/core/annotation/MirrorLinkAttributePostProcessorTest.java b/hutool-core/src/test/java/cn/hutool/core/annotation/MirrorLinkAttributePostProcessorTest.java new file mode 100644 index 000000000..d6e8902db --- /dev/null +++ b/hutool-core/src/test/java/cn/hutool/core/annotation/MirrorLinkAttributePostProcessorTest.java @@ -0,0 +1,192 @@ +package cn.hutool.core.annotation; + +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.ReflectUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.lang.annotation.*; +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.function.UnaryOperator; + +public class MirrorLinkAttributePostProcessorTest { + + @Test + public void processTest() { + MirrorLinkAttributePostProcessor processor = new MirrorLinkAttributePostProcessor(); + + Map, SynthesizedAnnotation> annotationMap = new HashMap<>(); + SynthesizedAnnotationAggregator synthesizedAnnotationAggregator = new TestSynthesizedAnnotationAggregator(annotationMap); + AnnotationForTest annotation = ClassForTest.class.getAnnotation(AnnotationForTest.class); + SynthesizedAnnotation synthesizedAnnotation = new TestSynthesizedAnnotation(synthesizedAnnotationAggregator, annotation); + annotationMap.put(annotation.annotationType(), synthesizedAnnotation); + + processor.process(synthesizedAnnotation, synthesizedAnnotationAggregator); + AnnotationAttribute valueAttribute = synthesizedAnnotation.getAttributes().get("value"); + Assert.assertEquals(ReflectUtil.getMethod(AnnotationForTest.class, "value"), valueAttribute.getAttribute()); + Assert.assertTrue(valueAttribute.isWrapped()); + Assert.assertEquals(MirroredAnnotationAttribute.class, valueAttribute.getClass()); + + AnnotationAttribute nameAttribute = synthesizedAnnotation.getAttributes().get("name"); + Assert.assertEquals(ReflectUtil.getMethod(AnnotationForTest.class, "name"), nameAttribute.getAttribute()); + Assert.assertTrue(nameAttribute.isWrapped()); + Assert.assertEquals(MirroredAnnotationAttribute.class, nameAttribute.getClass()); + + Assert.assertEquals(((WrappedAnnotationAttribute)nameAttribute).getLinked(), ((WrappedAnnotationAttribute)valueAttribute).getOriginal()); + Assert.assertEquals(((WrappedAnnotationAttribute)nameAttribute).getOriginal(), ((WrappedAnnotationAttribute)valueAttribute).getLinked()); + } + + @AnnotationForTest + static class ClassForTest {} + + @Retention(RetentionPolicy.RUNTIME) + @Target({ ElementType.METHOD, ElementType.TYPE }) + @interface AnnotationForTest { + @Link(attribute = "name", type = RelationType.MIRROR_FOR) + String value() default ""; + @Link(attribute = "value", type = RelationType.MIRROR_FOR) + String name() default ""; + } + + static class TestSynthesizedAnnotationAggregator implements SynthesizedAnnotationAggregator { + + private final Map, SynthesizedAnnotation> annotationMap; + + public TestSynthesizedAnnotationAggregator(Map, SynthesizedAnnotation> annotationMap) { + this.annotationMap = annotationMap; + } + + @Override + public SynthesizedAnnotationSelector getAnnotationSelector() { + return null; + } + + @Override + public SynthesizedAnnotationAttributeProcessor getAnnotationAttributeProcessor() { + return null; + } + + @Override + public Collection getAnnotationAttributePostProcessors() { + return null; + } + + @Override + public SynthesizedAnnotation getSynthesizedAnnotation(Class annotationType) { + return annotationMap.get(annotationType); + } + + @Override + public Collection getAllSynthesizedAnnotation() { + return null; + } + + @Override + public T getAnnotation(Class annotationType) { + return null; + } + + @Override + public boolean isAnnotationPresent(Class annotationType) { + return false; + } + + @Override + public Annotation[] getAnnotations() { + return new Annotation[0]; + } + + @Override + public T synthesize(Class annotationType) { + return null; + } + + @Override + public Object getAttribute(String attributeName, Class attributeType) { + return null; + } + + @Override + public Annotation[] getDeclaredAnnotations() { + return new Annotation[0]; + } + } + + static class TestSynthesizedAnnotation implements SynthesizedAnnotation { + + private final Annotation annotation; + private final SynthesizedAnnotationAggregator owner; + private final Map attributeMap; + + public TestSynthesizedAnnotation(SynthesizedAnnotationAggregator owner, Annotation annotation) { + this.owner = owner; + this.attributeMap = new HashMap<>(); + this.annotation = annotation; + for (Method declaredMethod : annotation.annotationType().getDeclaredMethods()) { + attributeMap.put(declaredMethod.getName(), new CacheableAnnotationAttribute(annotation, declaredMethod)); + } + } + + @Override + public SynthesizedAnnotationAggregator getOwner() { + return owner; + } + + @Override + public Object getRoot() { + return null; + } + + @Override + public Annotation getAnnotation() { + return annotation; + } + + @Override + public int getVerticalDistance() { + return 0; + } + + @Override + public int getHorizontalDistance() { + return 0; + } + + @Override + public boolean hasAttribute(String attributeName, Class returnType) { + return false; + } + + @Override + public Map getAttributes() { + return attributeMap; + } + + @Override + public void setAttribute(String attributeName, AnnotationAttribute attribute) { + attributeMap.put(attributeName, attribute); + } + + @Override + public void replaceAttribute(String attributeName, UnaryOperator operator) { + AnnotationAttribute annotationAttribute = attributeMap.get(attributeName); + if (ObjectUtil.isNotNull(annotationAttribute)) { + attributeMap.put(attributeName, operator.apply(annotationAttribute)); + } + } + + @Override + public Object getAttributeValue(String attributeName) { + return null; + } + + @Override + public Class annotationType() { + return annotation.annotationType(); + } + } + +} diff --git a/hutool-core/src/test/java/cn/hutool/core/annotation/SynthesizedAnnotationSelectorTest.java b/hutool-core/src/test/java/cn/hutool/core/annotation/SynthesizedAnnotationSelectorTest.java index e27f8fb05..cadb3d6f9 100644 --- a/hutool-core/src/test/java/cn/hutool/core/annotation/SynthesizedAnnotationSelectorTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/annotation/SynthesizedAnnotationSelectorTest.java @@ -10,8 +10,8 @@ import java.util.function.UnaryOperator; public class SynthesizedAnnotationSelectorTest { @Test - public void nearestAndOldestPriorityTest() { - final SynthesizedAnnotationSelector selector = SynthesizedAnnotationSelector.NEAREST_AND_OLDEST_PRIORITY; + public void chooseTest() { + final SynthesizedAnnotationSelector.NearestAndOldestPrioritySelector selector = (SynthesizedAnnotationSelector.NearestAndOldestPrioritySelector)SynthesizedAnnotationSelector.NEAREST_AND_OLDEST_PRIORITY; TestSynthesizedAnnotation annotation1 = new TestSynthesizedAnnotation(0, 0); TestSynthesizedAnnotation annotation2 = new TestSynthesizedAnnotation(0, 0); @@ -28,7 +28,7 @@ public class SynthesizedAnnotationSelectorTest { @Test public void nearestAndNewestPriorityTest() { - final SynthesizedAnnotationSelector selector = SynthesizedAnnotationSelector.NEAREST_AND_NEWEST_PRIORITY; + final SynthesizedAnnotationSelector.NearestAndNewestPrioritySelector selector = (SynthesizedAnnotationSelector.NearestAndNewestPrioritySelector)SynthesizedAnnotationSelector.NEAREST_AND_NEWEST_PRIORITY; TestSynthesizedAnnotation annotation1 = new TestSynthesizedAnnotation(0, 0); TestSynthesizedAnnotation annotation2 = new TestSynthesizedAnnotation(0, 0); @@ -45,7 +45,7 @@ public class SynthesizedAnnotationSelectorTest { @Test public void farthestAndOldestPriorityTest() { - final SynthesizedAnnotationSelector selector = SynthesizedAnnotationSelector.FARTHEST_AND_OLDEST_PRIORITY; + final SynthesizedAnnotationSelector.FarthestAndOldestPrioritySelector selector = (SynthesizedAnnotationSelector.FarthestAndOldestPrioritySelector)SynthesizedAnnotationSelector.FARTHEST_AND_OLDEST_PRIORITY; TestSynthesizedAnnotation annotation1 = new TestSynthesizedAnnotation(0, 0); TestSynthesizedAnnotation annotation2 = new TestSynthesizedAnnotation(0, 0); @@ -62,7 +62,7 @@ public class SynthesizedAnnotationSelectorTest { @Test public void farthestAndNewestPriorityTest() { - final SynthesizedAnnotationSelector selector = SynthesizedAnnotationSelector.FARTHEST_AND_NEWEST_PRIORITY; + final SynthesizedAnnotationSelector.FarthestAndNewestPrioritySelector selector = (SynthesizedAnnotationSelector.FarthestAndNewestPrioritySelector)SynthesizedAnnotationSelector.FARTHEST_AND_NEWEST_PRIORITY; TestSynthesizedAnnotation annotation1 = new TestSynthesizedAnnotation(0, 0); TestSynthesizedAnnotation annotation2 = new TestSynthesizedAnnotation(0, 0); @@ -88,7 +88,7 @@ public class SynthesizedAnnotationSelectorTest { } @Override - public SyntheticAnnotation getOwner() { + public SynthesizedAnnotationAggregator getOwner() { return null; } diff --git a/hutool-core/src/test/java/cn/hutool/core/annotation/SyntheticMetaAnnotationTest.java b/hutool-core/src/test/java/cn/hutool/core/annotation/SyntheticMetaAnnotationTest.java index c9e358883..b34f2d4dc 100644 --- a/hutool-core/src/test/java/cn/hutool/core/annotation/SyntheticMetaAnnotationTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/annotation/SyntheticMetaAnnotationTest.java @@ -9,7 +9,7 @@ import java.lang.reflect.Method; import java.util.Arrays; /** - * 合成注解{@link SyntheticMetaAnnotation}的测试用例 + * 合成注解{@link SynthesizedMetaAnnotationAggregator}的测试用例 * * @author huangchengxing */ @@ -22,10 +22,10 @@ public class SyntheticMetaAnnotationTest { final GrandParentAnnotation grandParentAnnotation = ChildAnnotation.class.getAnnotation(GrandParentAnnotation.class); final ParentAnnotation parentAnnotation = ChildAnnotation.class.getAnnotation(ParentAnnotation.class); final ChildAnnotation childAnnotation = AnnotatedClass.class.getAnnotation(ChildAnnotation.class); - final SyntheticMetaAnnotation syntheticMetaAnnotation = new SyntheticMetaAnnotation(childAnnotation); + final SynthesizedMetaAnnotationAggregator syntheticMetaAnnotation = new SynthesizedMetaAnnotationAggregator(childAnnotation); // Annotation & AnnotatedElement - Assert.assertEquals(SyntheticMetaAnnotation.class, syntheticMetaAnnotation.annotationType()); + Assert.assertEquals(SynthesizedMetaAnnotationAggregator.class, syntheticMetaAnnotation.annotationType()); Assert.assertTrue(syntheticMetaAnnotation.isAnnotationPresent(GrandParentAnnotation.class)); Assert.assertTrue(syntheticMetaAnnotation.isAnnotationPresent(ParentAnnotation.class)); Assert.assertTrue(syntheticMetaAnnotation.isAnnotationPresent(ChildAnnotation.class)); @@ -42,15 +42,20 @@ public class SyntheticMetaAnnotationTest { Assert.assertNotNull(syntheticMetaAnnotation.getSynthesizedAnnotation(GrandParentAnnotation.class)); Assert.assertNotNull(syntheticMetaAnnotation.getSynthesizedAnnotation(ParentAnnotation.class)); Assert.assertNotNull(syntheticMetaAnnotation.getSynthesizedAnnotation(ChildAnnotation.class)); - Assert.assertEquals(3, syntheticMetaAnnotation.getAllSyntheticAnnotations().size()); + Assert.assertEquals(3, syntheticMetaAnnotation.getAllSynthesizedAnnotation().size()); + + // 属性 + Assert.assertEquals(SynthesizedAnnotationSelector.NEAREST_AND_OLDEST_PRIORITY, syntheticMetaAnnotation.getAnnotationSelector()); + Assert.assertEquals(CacheableSynthesizedAnnotationAttributeProcessor.class, syntheticMetaAnnotation.getAnnotationAttributeProcessor().getClass()); + Assert.assertEquals(3, syntheticMetaAnnotation.getAnnotationAttributePostProcessors().size()); } @Test public void synthesisAnnotationAttributeTest() { final ChildAnnotation rootAnnotation = AnnotatedClass.class.getAnnotation(ChildAnnotation.class); - SyntheticMetaAnnotation syntheticMetaAnnotation = new SyntheticMetaAnnotation(rootAnnotation); + SynthesizedMetaAnnotationAggregator syntheticMetaAnnotation = new SynthesizedMetaAnnotationAggregator(rootAnnotation); Assert.assertEquals(syntheticMetaAnnotation.getSource(), rootAnnotation); - Assert.assertEquals(syntheticMetaAnnotation.annotationType(), SyntheticMetaAnnotation.class); + Assert.assertEquals(syntheticMetaAnnotation.annotationType(), SynthesizedMetaAnnotationAggregator.class); Assert.assertEquals(1, syntheticMetaAnnotation.getDeclaredAnnotations().length); Assert.assertEquals(syntheticMetaAnnotation.getDeclaredAnnotations()[0], rootAnnotation); Assert.assertEquals(3, syntheticMetaAnnotation.getAnnotations().length); @@ -59,35 +64,55 @@ public class SyntheticMetaAnnotationTest { Assert.assertEquals("Child!", syntheticMetaAnnotation.getAttribute("childValueAlias", String.class)); Assert.assertEquals("Child's Parent!", syntheticMetaAnnotation.getAttribute("parentValue", String.class)); Assert.assertEquals("Child's GrandParent!", syntheticMetaAnnotation.getAttribute("grandParentValue", String.class)); + } - final ChildAnnotation childAnnotation = syntheticMetaAnnotation.syntheticAnnotation(ChildAnnotation.class); + @Test + public void syntheticAnnotationTest() { + final ChildAnnotation rootAnnotation = AnnotatedClass.class.getAnnotation(ChildAnnotation.class); + SynthesizedMetaAnnotationAggregator syntheticMetaAnnotation = new SynthesizedMetaAnnotationAggregator(rootAnnotation); + + final ChildAnnotation childAnnotation = syntheticMetaAnnotation.synthesize(ChildAnnotation.class); + SynthesizedAnnotation childSyntheticAnnotation = syntheticMetaAnnotation.getSynthesizedAnnotation(ChildAnnotation.class); + Assert.assertNotNull(childSyntheticAnnotation); + Assert.assertTrue(childSyntheticAnnotation.hasAttribute("childValue", String.class)); + Assert.assertEquals(AnnotatedClass.class.getAnnotation(ChildAnnotation.class), childSyntheticAnnotation.getRoot()); + Assert.assertEquals(AnnotatedClass.class.getAnnotation(ChildAnnotation.class), childSyntheticAnnotation.getAnnotation()); Assert.assertTrue(syntheticMetaAnnotation.isAnnotationPresent(ChildAnnotation.class)); Assert.assertNotNull(childAnnotation); Assert.assertEquals("Child!", childAnnotation.childValue()); Assert.assertEquals("Child!", childAnnotation.childValueAlias()); Assert.assertEquals(childAnnotation.grandParentType(), Integer.class); - Assert.assertThrows(IllegalArgumentException.class, () -> new SyntheticMetaAnnotation(childAnnotation)); + Assert.assertThrows(IllegalArgumentException.class, () -> new SynthesizedMetaAnnotationAggregator(childAnnotation)); - final ParentAnnotation parentAnnotation = syntheticMetaAnnotation.syntheticAnnotation(ParentAnnotation.class); - Assert.assertTrue(syntheticMetaAnnotation.isAnnotationPresent(ParentAnnotation.class)); + final ParentAnnotation parentAnnotation = syntheticMetaAnnotation.synthesize(ParentAnnotation.class); + SynthesizedAnnotation parentSyntheticAnnotation = syntheticMetaAnnotation.getSynthesizedAnnotation(ParentAnnotation.class); + Assert.assertNotNull(parentSyntheticAnnotation); + Assert.assertTrue(parentSyntheticAnnotation.hasAttribute("parentValue", String.class)); + Assert.assertEquals(AnnotatedClass.class.getAnnotation(ChildAnnotation.class), parentSyntheticAnnotation.getRoot()); + Assert.assertEquals(ChildAnnotation.class.getAnnotation(ParentAnnotation.class), parentSyntheticAnnotation.getAnnotation()); Assert.assertNotNull(parentAnnotation); Assert.assertEquals("Child's Parent!", parentAnnotation.parentValue()); Assert.assertEquals("java.lang.Void", parentAnnotation.grandParentType()); - Assert.assertThrows(IllegalArgumentException.class, () -> new SyntheticMetaAnnotation(parentAnnotation)); + Assert.assertThrows(IllegalArgumentException.class, () -> new SynthesizedMetaAnnotationAggregator(parentAnnotation)); - final GrandParentAnnotation grandParentAnnotation = syntheticMetaAnnotation.syntheticAnnotation(GrandParentAnnotation.class); + final GrandParentAnnotation grandParentAnnotation = syntheticMetaAnnotation.synthesize(GrandParentAnnotation.class); + SynthesizedAnnotation grandParentSyntheticAnnotation = syntheticMetaAnnotation.getSynthesizedAnnotation(GrandParentAnnotation.class); + Assert.assertNotNull(grandParentSyntheticAnnotation); + Assert.assertTrue(grandParentSyntheticAnnotation.hasAttribute("grandParentType", Class.class)); + Assert.assertEquals(AnnotatedClass.class.getAnnotation(ChildAnnotation.class), grandParentSyntheticAnnotation.getRoot()); + Assert.assertEquals(ChildAnnotation.class.getAnnotation(GrandParentAnnotation.class), grandParentSyntheticAnnotation.getAnnotation()); Assert.assertTrue(syntheticMetaAnnotation.isAnnotationPresent(GrandParentAnnotation.class)); Assert.assertNotNull(grandParentAnnotation); Assert.assertEquals("Child's GrandParent!", grandParentAnnotation.grandParentValue()); Assert.assertEquals(grandParentAnnotation.grandParentType(), Integer.class); - Assert.assertThrows(IllegalArgumentException.class, () -> new SyntheticMetaAnnotation(grandParentAnnotation)); + Assert.assertThrows(IllegalArgumentException.class, () -> new SynthesizedMetaAnnotationAggregator(grandParentAnnotation)); } @Test public void linkTest() { final Method method = ReflectUtil.getMethod(AnnotationForLinkTest.class, "value"); - final SyntheticAnnotation syntheticAnnotation = new SyntheticMetaAnnotation(method.getAnnotation(AliasFor.class)); - final Link link = syntheticAnnotation.syntheticAnnotation(Link.class); + final SynthesizedAnnotationAggregator synthesizedAnnotationAggregator = new SynthesizedMetaAnnotationAggregator(method.getAnnotation(AliasFor.class)); + final Link link = synthesizedAnnotationAggregator.synthesize(Link.class); Assert.assertEquals(AnnotationForLinkTest.class, link.annotation()); Assert.assertEquals("name", link.attribute()); } @@ -95,20 +120,20 @@ public class SyntheticMetaAnnotationTest { @Test public void mirrorAttributeTest() { AnnotationForMirrorTest annotation = ClassForMirrorTest.class.getAnnotation(AnnotationForMirrorTest.class); - SyntheticAnnotation synthetic = new SyntheticMetaAnnotation(annotation); - AnnotationForMirrorTest syntheticAnnotation = synthetic.syntheticAnnotation(AnnotationForMirrorTest.class); + SynthesizedAnnotationAggregator synthetic = new SynthesizedMetaAnnotationAggregator(annotation); + AnnotationForMirrorTest syntheticAnnotation = synthetic.synthesize(AnnotationForMirrorTest.class); Assert.assertEquals("Foo", syntheticAnnotation.name()); Assert.assertEquals("Foo", syntheticAnnotation.value()); annotation = ClassForMirrorTest2.class.getAnnotation(AnnotationForMirrorTest.class); - synthetic = new SyntheticMetaAnnotation(annotation); - syntheticAnnotation = synthetic.syntheticAnnotation(AnnotationForMirrorTest.class); + synthetic = new SynthesizedMetaAnnotationAggregator(annotation); + syntheticAnnotation = synthetic.synthesize(AnnotationForMirrorTest.class); Assert.assertEquals("Foo", syntheticAnnotation.name()); Assert.assertEquals("Foo", syntheticAnnotation.value()); annotation = ClassForMirrorTest3.class.getAnnotation(AnnotationForMirrorTest.class); - synthetic = new SyntheticMetaAnnotation(annotation); - syntheticAnnotation = synthetic.syntheticAnnotation(AnnotationForMirrorTest.class); + synthetic = new SynthesizedMetaAnnotationAggregator(annotation); + syntheticAnnotation = synthetic.synthesize(AnnotationForMirrorTest.class); AnnotationForMirrorTest finalSyntheticAnnotation = syntheticAnnotation; Assert.assertThrows(IllegalArgumentException.class, finalSyntheticAnnotation::name); } @@ -116,71 +141,71 @@ public class SyntheticMetaAnnotationTest { @Test public void aliasForTest() { AnnotationForAliasForTest annotation = ClassForAliasForTest.class.getAnnotation(AnnotationForAliasForTest.class); - SyntheticAnnotation synthetic = new SyntheticMetaAnnotation(annotation); - MetaAnnotationForAliasForTest metaAnnotation = synthetic.syntheticAnnotation(MetaAnnotationForAliasForTest.class); + SynthesizedAnnotationAggregator synthetic = new SynthesizedMetaAnnotationAggregator(annotation); + MetaAnnotationForAliasForTest metaAnnotation = synthetic.synthesize(MetaAnnotationForAliasForTest.class); Assert.assertEquals("Meta", metaAnnotation.name()); - AnnotationForAliasForTest childAnnotation = synthetic.syntheticAnnotation(AnnotationForAliasForTest.class); + AnnotationForAliasForTest childAnnotation = synthetic.synthesize(AnnotationForAliasForTest.class); Assert.assertEquals("", childAnnotation.value()); annotation = ClassForAliasForTest2.class.getAnnotation(AnnotationForAliasForTest.class); - synthetic = new SyntheticMetaAnnotation(annotation); - metaAnnotation = synthetic.syntheticAnnotation(MetaAnnotationForAliasForTest.class); + synthetic = new SynthesizedMetaAnnotationAggregator(annotation); + metaAnnotation = synthetic.synthesize(MetaAnnotationForAliasForTest.class); Assert.assertEquals("Foo", metaAnnotation.name()); - childAnnotation = synthetic.syntheticAnnotation(AnnotationForAliasForTest.class); + childAnnotation = synthetic.synthesize(AnnotationForAliasForTest.class); Assert.assertEquals("Foo", childAnnotation.value()); } @Test public void forceAliasForTest() { AnnotationForceForAliasForTest annotation = ClassForForceAliasForTest.class.getAnnotation(AnnotationForceForAliasForTest.class); - SyntheticAnnotation synthetic = new SyntheticMetaAnnotation(annotation); - MetaAnnotationForForceAliasForTest metaAnnotation = synthetic.syntheticAnnotation(MetaAnnotationForForceAliasForTest.class); + SynthesizedAnnotationAggregator synthetic = new SynthesizedMetaAnnotationAggregator(annotation); + MetaAnnotationForForceAliasForTest metaAnnotation = synthetic.synthesize(MetaAnnotationForForceAliasForTest.class); Assert.assertEquals("", metaAnnotation.name()); - AnnotationForceForAliasForTest childAnnotation = synthetic.syntheticAnnotation(AnnotationForceForAliasForTest.class); + AnnotationForceForAliasForTest childAnnotation = synthetic.synthesize(AnnotationForceForAliasForTest.class); Assert.assertEquals("", childAnnotation.value()); annotation = ClassForForceAliasForTest2.class.getAnnotation(AnnotationForceForAliasForTest.class); - synthetic = new SyntheticMetaAnnotation(annotation); - metaAnnotation = synthetic.syntheticAnnotation(MetaAnnotationForForceAliasForTest.class); + synthetic = new SynthesizedMetaAnnotationAggregator(annotation); + metaAnnotation = synthetic.synthesize(MetaAnnotationForForceAliasForTest.class); Assert.assertEquals("Foo", metaAnnotation.name()); - childAnnotation = synthetic.syntheticAnnotation(AnnotationForceForAliasForTest.class); + childAnnotation = synthetic.synthesize(AnnotationForceForAliasForTest.class); Assert.assertEquals("Foo", childAnnotation.value()); } @Test public void aliasForAndMirrorTest() { AnnotationForMirrorThenAliasForTest annotation = ClassForAliasForAndMirrorTest.class.getAnnotation(AnnotationForMirrorThenAliasForTest.class); - SyntheticAnnotation synthetic = new SyntheticMetaAnnotation(annotation); - MetaAnnotationForMirrorThenAliasForTest metaAnnotation = synthetic.syntheticAnnotation(MetaAnnotationForMirrorThenAliasForTest.class); + SynthesizedAnnotationAggregator synthetic = new SynthesizedMetaAnnotationAggregator(annotation); + MetaAnnotationForMirrorThenAliasForTest metaAnnotation = synthetic.synthesize(MetaAnnotationForMirrorThenAliasForTest.class); Assert.assertEquals("test", metaAnnotation.name()); Assert.assertEquals("test", metaAnnotation.value()); - AnnotationForMirrorThenAliasForTest childAnnotation = synthetic.syntheticAnnotation(AnnotationForMirrorThenAliasForTest.class); + AnnotationForMirrorThenAliasForTest childAnnotation = synthetic.synthesize(AnnotationForMirrorThenAliasForTest.class); Assert.assertEquals("test", childAnnotation.childValue()); } @Test public void multiAliasForTest() { final AnnotationForMultiAliasForTest annotation = ClassForMultiAliasForTest.class.getAnnotation(AnnotationForMultiAliasForTest.class); - final SyntheticAnnotation synthetic = new SyntheticMetaAnnotation(annotation); + final SynthesizedAnnotationAggregator synthetic = new SynthesizedMetaAnnotationAggregator(annotation); - final MetaAnnotationForMultiAliasForTest1 metaAnnotation1 = synthetic.syntheticAnnotation(MetaAnnotationForMultiAliasForTest1.class); + final MetaAnnotationForMultiAliasForTest1 metaAnnotation1 = synthetic.synthesize(MetaAnnotationForMultiAliasForTest1.class); Assert.assertEquals("test", metaAnnotation1.name()); Assert.assertEquals("test", metaAnnotation1.value1()); - final MetaAnnotationForMultiAliasForTest2 metaAnnotation2 = synthetic.syntheticAnnotation(MetaAnnotationForMultiAliasForTest2.class); + final MetaAnnotationForMultiAliasForTest2 metaAnnotation2 = synthetic.synthesize(MetaAnnotationForMultiAliasForTest2.class); Assert.assertEquals("test", metaAnnotation2.value2()); - final AnnotationForMultiAliasForTest childAnnotation = synthetic.syntheticAnnotation(AnnotationForMultiAliasForTest.class); + final AnnotationForMultiAliasForTest childAnnotation = synthetic.synthesize(AnnotationForMultiAliasForTest.class); Assert.assertEquals("test", childAnnotation.value3()); } @Test public void implicitAliasTest() { final AnnotationForImplicitAliasTest annotation = ClassForImplicitAliasTest.class.getAnnotation(AnnotationForImplicitAliasTest.class); - final SyntheticAnnotation synthetic = new SyntheticMetaAnnotation(annotation); + final SynthesizedAnnotationAggregator synthetic = new SynthesizedMetaAnnotationAggregator(annotation); - final MetaAnnotationForImplicitAliasTest metaAnnotation = synthetic.syntheticAnnotation(MetaAnnotationForImplicitAliasTest.class); + final MetaAnnotationForImplicitAliasTest metaAnnotation = synthetic.synthesize(MetaAnnotationForImplicitAliasTest.class); Assert.assertEquals("Meta", metaAnnotation.name()); Assert.assertEquals("Foo", metaAnnotation.value()); - final AnnotationForImplicitAliasTest childAnnotation = synthetic.syntheticAnnotation(AnnotationForImplicitAliasTest.class); + final AnnotationForImplicitAliasTest childAnnotation = synthetic.synthesize(AnnotationForImplicitAliasTest.class); Assert.assertEquals("Foo", childAnnotation.value()); }