优化代码,调整变量、方法与类名,完善测试用例

This commit is contained in:
huangchengxing 2022-07-13 22:39:41 +08:00
parent b29b0c3932
commit a352783b5c
20 changed files with 625 additions and 482 deletions

View File

@ -0,0 +1,160 @@
package cn.hutool.core.annotation;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.Map;
/**
* {@link SynthesizedAnnotationPostProcessor}的基本实现
* 用于处理注解中带有{@link Link}注解的属性
*
* @author huangchengxing
* @see MirrorLinkAnnotationPostProcessor
* @see AliasLinkAnnotationPostProcessor
*/
public abstract class AbstractLinkAnnotationPostProcessor implements SynthesizedAnnotationPostProcessor {
/**
* 若一个注解属性上存在{@link Link}注解注解的{@link Link#type()}返回值在{@link #processTypes()}中存在
* 且此{@link Link}指定的注解对象在当前的{@link SynthesizedAnnotationAggregator}中存在
* 则从聚合器中获取类型对应的合成注解对象与该对象中的指定属性然后将全部关联数据交给
* {@link #processLinkedAttribute}处理
*
* @param synthesizedAnnotation 合成的注解
* @param aggregator 合成注解聚合器
*/
@Override
public void process(SynthesizedAnnotation synthesizedAnnotation, SynthesizedAnnotationAggregator aggregator) {
final Map<String, AnnotationAttribute> attributeMap = new HashMap<>(synthesizedAnnotation.getAttributes());
attributeMap.forEach((originalAttributeName, originalAttribute) -> {
// 获取注解
final Link link = getLinkAnnotation(originalAttribute, processTypes());
if (ObjectUtil.isNull(link)) {
return;
}
// 获取注解属性
final SynthesizedAnnotation linkedAnnotation = getLinkedAnnotation(link, aggregator, synthesizedAnnotation.annotationType());
if (ObjectUtil.isNull(linkedAnnotation)) {
return;
}
final AnnotationAttribute linkedAttribute = linkedAnnotation.getAttributes().get(link.attribute());
// 处理
processLinkedAttribute(aggregator, link, synthesizedAnnotation, originalAttribute,
linkedAnnotation, linkedAttribute
);
});
}
// =========================== 抽象方法 ===========================
/**
* 当属性上存在{@link Link}注解时仅当{@link Link#type()}在本方法返回值内存在时才进行处理
*
* @return 支持处理的{@link RelationType}类型
*/
protected abstract RelationType[] processTypes();
/**
* 对关联的合成注解对象及其关联属性的处理
*
* @param aggregator 合成注解聚合器
* @param annotation {@code originalAttribute}上的{@link Link}注解对象
* @param originalAnnotation 当前正在处理的{@link SynthesizedAnnotation}对象
* @param originalAttribute {@code originalAnnotation}上的待处理的属性
* @param linkedAnnotation {@link Link}指向的关联注解对象
* @param linkedAttribute {@link Link}指向的{@code originalAnnotation}中的关联属性该参数可能为空
*/
protected abstract void processLinkedAttribute(
SynthesizedAnnotationAggregator aggregator, Link annotation,
SynthesizedAnnotation originalAnnotation, AnnotationAttribute originalAttribute,
SynthesizedAnnotation linkedAnnotation, AnnotationAttribute linkedAttribute
);
// =========================== @Link注解的处理 ===========================
/**
* 从注解属性上获取指定类型的{@link Link}注解
*
* @param attribute 注解属性
* @param relationTypes 类型
* @return 注解
*/
protected Link getLinkAnnotation(AnnotationAttribute attribute, RelationType... relationTypes) {
return Opt.ofNullable(attribute)
.map(t -> AnnotationUtil.getSynthesizedAnnotation(attribute.getAttribute(), Link.class))
.filter(a -> ArrayUtil.contains(relationTypes, a.type()))
.get();
}
/**
* 从合成注解中获取{@link Link#type()}指定的注解对象
*
* @param annotation {@link Link}注解
* @param synthesizedAnnotationAggregator 合成注解
*/
protected SynthesizedAnnotation getLinkedAnnotation(
Link annotation, SynthesizedAnnotationAggregator synthesizedAnnotationAggregator, Class<? extends Annotation> defaultType) {
final Class<?> targetAnnotationType = getLinkedAnnotationType(annotation, defaultType);
return synthesizedAnnotationAggregator.getSynthesizedAnnotation(targetAnnotationType);
}
/**
* {@link Link#annotation()}获取的类型{@link Annotation#getClass()}则返回{@code defaultType}
* 否则返回{@link Link#annotation()}指定的类型
*
* @param annotation {@link Link}注解
* @param defaultType 默认注解类型
* @return 注解类型
*/
protected Class<?> getLinkedAnnotationType(Link annotation, Class<?> defaultType) {
return ObjectUtil.equals(annotation.annotation(), Annotation.class) ?
defaultType : annotation.annotation();
}
// =========================== 注解属性的校验 ===========================
/**
* 校验两个注解属性的返回值类型是否一致
*
* @param original 原属性
* @param alias 别名属性
*/
protected void checkAttributeType(AnnotationAttribute original, AnnotationAttribute alias) {
Assert.equals(
original.getAttributeType(), alias.getAttributeType(),
"return type of the linked attribute [{}] is inconsistent with the original [{}]",
original.getAttribute(), alias.getAttribute()
);
}
/**
* 检查{@link Link}指向的注解属性是否就是本身
*
* @param original {@link Link}注解的属性
* @param linked {@link Link}指向的注解属性
*/
protected 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}指向的注解属性是否存在
*
* @param original {@link Link}注解的属性
* @param linkedAttribute {@link Link}指向的注解属性
* @param annotation {@link Link}注解
*/
protected void checkLinkedAttributeNotNull(AnnotationAttribute original, AnnotationAttribute linkedAttribute, Link annotation) {
Assert.notNull(linkedAttribute, "cannot find linked attribute [{}] of original [{}] in [{}]",
original.getAttribute(), annotation.attribute(),
getLinkedAnnotationType(annotation, original.getAnnotationType())
);
}
}

View File

@ -0,0 +1,195 @@
package cn.hutool.core.annotation;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ObjectUtil;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* {@link SynthesizedAnnotation}的基本实现
*
* @param <R> 根对象类型
* @author huangchengxing
*/
public abstract class AbstractSynthesizedAnnotation<R> implements Annotation, SynthesizedAnnotation {
private final SynthesizedAnnotationAggregator owner;
private final R root;
private final Annotation annotation;
private final Map<String, AnnotationAttribute> attributeMethodCaches;
private final int verticalDistance;
private final int horizontalDistance;
/**
* 创建一个合成注解
*
* @param owner 合成注解所属的合成注解聚合器
* @param root 根对象
* @param annotation 被合成的注解对象
* @param verticalDistance 距离根对象的水平距离
* @param horizontalDistance 距离根对象的垂直距离
*/
protected AbstractSynthesizedAnnotation(
SynthesizedAnnotationAggregator owner, R root, Annotation annotation, int verticalDistance, int horizontalDistance) {
this.owner = owner;
this.root = root;
this.annotation = annotation;
this.verticalDistance = verticalDistance;
this.horizontalDistance = horizontalDistance;
this.attributeMethodCaches = new HashMap<>();
this.attributeMethodCaches.putAll(loadAttributeMethods());
}
/**
* 加载注解属性
*
* @return 注解属性
*/
protected Map<String, AnnotationAttribute> loadAttributeMethods() {
return Stream.of(annotation.annotationType().getDeclaredMethods())
.filter(AnnotationUtil::isAttributeMethod)
.collect(Collectors.toMap(Method::getName, method -> new CacheableAnnotationAttribute(annotation, method)));
}
/**
* 元注解是否存在该属性
*
* @param attributeName 属性名
* @return 是否存在该属性
*/
public boolean hasAttribute(String attributeName) {
return attributeMethodCaches.containsKey(attributeName);
}
/**
* 元注解是否存在该属性且该属性的值类型是指定类型或其子类
*
* @param attributeName 属性名
* @param returnType 返回值类型
* @return 是否存在该属性
*/
@Override
public boolean hasAttribute(String attributeName, Class<?> returnType) {
return Opt.ofNullable(attributeMethodCaches.get(attributeName))
.filter(method -> ClassUtil.isAssignable(returnType, method.getAttributeType()))
.isPresent();
}
/**
* 获取该注解的全部属性
*
* @return 注解属性
*/
@Override
public Map<String, AnnotationAttribute> getAttributes() {
return this.attributeMethodCaches;
}
/**
* 设置属性值
*
* @param attributeName 属性名称
* @param attribute 注解属性
*/
@Override
public void setAttribute(String attributeName, AnnotationAttribute attribute) {
attributeMethodCaches.put(attributeName, attribute);
}
/**
* 替换属性值
*
* @param attributeName 属性名
* @param operator 替换操作
*/
@Override
public void replaceAttribute(String attributeName, UnaryOperator<AnnotationAttribute> operator) {
AnnotationAttribute old = attributeMethodCaches.get(attributeName);
if (ObjectUtil.isNotNull(old)) {
attributeMethodCaches.put(attributeName, operator.apply(old));
}
}
/**
* 获取属性值
*
* @param attributeName 属性名
* @return 属性值
*/
@Override
public Object getAttributeValue(String attributeName) {
return Opt.ofNullable(attributeMethodCaches.get(attributeName))
.map(AnnotationAttribute::getValue)
.get();
}
/**
* 获取所属的合成注解集合器
*
* @return 合成注解
*/
@Override
public SynthesizedAnnotationAggregator getOwner() {
return owner;
}
/**
* 获取该合成注解对应的根节点
*
* @return 合成注解对应的根节点
*/
@Override
public R getRoot() {
return root;
}
/**
* 获取被合成的注解对象
*
* @return 注解对象
*/
@Override
public Annotation getAnnotation() {
return annotation;
}
/**
* 获取该合成注解与根对象的垂直距离
* 默认情况下该距离即为当前注解与根对象之间相隔的层级数
*
* @return 合成注解与根对象的垂直距离
*/
@Override
public int getVerticalDistance() {
return verticalDistance;
}
/**
* 获取该合成注解与根对象的水平距离
* 默认情况下该距离即为当前注解与根对象之间相隔的已经被扫描到的注解数
*
* @return 合成注解与根对象的水平距离
*/
@Override
public int getHorizontalDistance() {
return horizontalDistance;
}
/**
* 获取被合成的注解类型
*
* @return 被合成的注解类型
*/
@Override
public Class<? extends Annotation> annotationType() {
return annotation.annotationType();
}
}

View File

@ -11,13 +11,15 @@ import cn.hutool.core.util.ObjectUtil;
import java.util.Map; import java.util.Map;
/** /**
* 用于处理合成注解属性中{@link Alias}的映射关系 * <p>用于处理注解对象中带有{@link Alias}注解的属性<br>
* 该处理器会令{@link Alias#value()}指向的属性值强制覆盖当前属性 * 当该处理器执行完毕后{@link Alias}注解指向的目标注解的属性将会被包装并替换为
* {@link ForceAliasedAnnotationAttribute}
* *
* @author huangchengxing * @author huangchengxing
* @see Alias
* @see ForceAliasedAnnotationAttribute * @see ForceAliasedAnnotationAttribute
*/ */
public class AliasAttributePostProcessor implements SynthesizedAnnotationPostProcessor { public class AliasAnnotationPostProcessor implements SynthesizedAnnotationPostProcessor {
@Override @Override
public int order() { public int order() {
@ -25,8 +27,8 @@ public class AliasAttributePostProcessor implements SynthesizedAnnotationPostPro
} }
@Override @Override
public void process(SynthesizedAnnotation annotation, SynthesizedAnnotationAggregator synthesizedAnnotationAggregator) { public void process(SynthesizedAnnotation synthesizedAnnotation, SynthesizedAnnotationAggregator aggregator) {
final Map<String, AnnotationAttribute> attributeMap = annotation.getAttributes(); final Map<String, AnnotationAttribute> attributeMap = synthesizedAnnotation.getAttributes();
// 记录别名与属性的关系 // 记录别名与属性的关系
final ForestMap<String, AnnotationAttribute> attributeAliasMappings = new LinkedForestMap<>(false); final ForestMap<String, AnnotationAttribute> attributeAliasMappings = new LinkedForestMap<>(false);
@ -58,7 +60,7 @@ public class AliasAttributePostProcessor implements SynthesizedAnnotationPostPro
attributeMap.put(attributeName, new ForceAliasedAnnotationAttribute(attribute, resolvedAttribute)); attributeMap.put(attributeName, new ForceAliasedAnnotationAttribute(attribute, resolvedAttribute));
} }
}); });
annotation.setAttributes(attributeMap); synthesizedAnnotation.setAttributes(attributeMap);
} }
} }

View File

@ -1,106 +0,0 @@
package cn.hutool.core.annotation;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.util.ObjectUtil;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BinaryOperator;
/**
* 处理注解中带有{@link Link}注解{@link Link#type()}{@link RelationType#FORCE_ALIAS_FOR}
* {@link RelationType#ALIAS_FOR}的属性
*
* @author huangchengxing
* @see ForceAliasedAnnotationAttribute
* @see AliasedAnnotationAttribute
*/
public class AliasForLinkAttributePostProcessor implements SynthesizedAnnotationPostProcessor {
@Override
public int order() {
return Integer.MIN_VALUE + 2;
}
@Override
public void process(SynthesizedAnnotation annotation, SynthesizedAnnotationAggregator synthesizedAnnotationAggregator) {
final Map<String, AnnotationAttribute> attributeMap = new HashMap<>(annotation.getAttributes());
attributeMap.forEach((originalAttributeName, originalAttribute) -> {
// 获取注解
final Link link = SyntheticAnnotationUtil.getLink(
originalAttribute, RelationType.ALIAS_FOR, RelationType.FORCE_ALIAS_FOR
);
if (ObjectUtil.isNull(link)) {
return;
}
// 获取注解属性
final SynthesizedAnnotation aliasAnnotation = SyntheticAnnotationUtil.getLinkedAnnotation(link, synthesizedAnnotationAggregator, annotation.annotationType());
if (ObjectUtil.isNull(aliasAnnotation)) {
return;
}
final AnnotationAttribute aliasAttribute = aliasAnnotation.getAttributes().get(link.attribute());
SyntheticAnnotationUtil.checkLinkedAttributeNotNull(originalAttribute, aliasAttribute, link);
SyntheticAnnotationUtil.checkAttributeType(originalAttribute, aliasAttribute);
checkCircularDependency(originalAttribute, aliasAttribute);
// aliasFor
if (RelationType.ALIAS_FOR.equals(link.type())) {
wrappingLinkedAttribute(synthesizedAnnotationAggregator, originalAttribute, aliasAttribute, AliasedAnnotationAttribute::new);
return;
}
// forceAliasFor
wrappingLinkedAttribute(synthesizedAnnotationAggregator, originalAttribute, aliasAttribute, ForceAliasedAnnotationAttribute::new);
});
}
/**
* 对指定注解属性进行包装若该属性已被包装过则递归以其为根节点的树结构对树上全部的叶子节点进行包装
*/
private void wrappingLinkedAttribute(
SynthesizedAnnotationAggregator synthesizedAnnotationAggregator, AnnotationAttribute originalAttribute, AnnotationAttribute aliasAttribute, BinaryOperator<AnnotationAttribute> wrapping) {
// 不是包装属性
if (!aliasAttribute.isWrapped()) {
processAttribute(synthesizedAnnotationAggregator, originalAttribute, aliasAttribute, wrapping);
return;
}
// 是包装属性
final AbstractWrappedAnnotationAttribute wrapper = (AbstractWrappedAnnotationAttribute)aliasAttribute;
wrapper.getAllLinkedNonWrappedAttributes().forEach(
t -> processAttribute(synthesizedAnnotationAggregator, originalAttribute, t, wrapping)
);
}
/**
* 获取指定注解属性然后将其再进行一层包装
*/
private void processAttribute(
SynthesizedAnnotationAggregator synthesizedAnnotationAggregator, AnnotationAttribute originalAttribute,
AnnotationAttribute target, BinaryOperator<AnnotationAttribute> wrapping) {
Opt.ofNullable(target.getAnnotationType())
.map(synthesizedAnnotationAggregator::getSynthesizedAnnotation)
.ifPresent(t -> t.replaceAttribute(target.getAttributeName(), old -> wrapping.apply(old, originalAttribute)));
}
/**
* 检查两个属性是否互为别名
*/
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;
}
final Class<?> aliasAnnotationType = SyntheticAnnotationUtil.getLinkedAnnotationType(annotation, alias.getAnnotationType());
if (ObjectUtil.notEqual(aliasAnnotationType, original.getAnnotationType())) {
return;
}
Assert.notEquals(
annotation.attribute(), original.getAttributeName(),
"circular reference between the alias attribute [{}] and the original attribute [{}]",
alias.getAttribute(), original.getAttribute()
);
}
}

View File

@ -0,0 +1,126 @@
package cn.hutool.core.annotation;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.util.ObjectUtil;
import java.util.function.BinaryOperator;
/**
* <p>用于处理注解对象中带有{@link Link}注解{@link Link#type()}
* {@link RelationType#ALIAS_FOR}{@link RelationType#FORCE_ALIAS_FOR}的属性<br>
* 当该处理器执行完毕后{@link Link}注解指向的目标注解的属性将会被包装并替换为
* {@link AliasedAnnotationAttribute}{@link ForceAliasedAnnotationAttribute}
*
* @author huangchengxing
* @see RelationType#ALIAS_FOR
* @see AliasedAnnotationAttribute
* @see RelationType#FORCE_ALIAS_FOR
* @see ForceAliasedAnnotationAttribute
*/
public class AliasLinkAnnotationPostProcessor extends AbstractLinkAnnotationPostProcessor {
private static final RelationType[] PROCESSED_RELATION_TYPES = new RelationType[]{ RelationType.ALIAS_FOR, RelationType.FORCE_ALIAS_FOR };
@Override
public int order() {
return Integer.MIN_VALUE + 2;
}
/**
* 该处理器只处理{@link Link#type()}类型为{@link RelationType#ALIAS_FOR}{@link RelationType#FORCE_ALIAS_FOR}的注解属性
*
* @return 含有{@link RelationType#ALIAS_FOR}{@link RelationType#FORCE_ALIAS_FOR}的数组
*/
@Override
protected RelationType[] processTypes() {
return PROCESSED_RELATION_TYPES;
}
/**
* 获取{@link Link}指向的目标注解属性并根据{@link Link#type()}的类型是
* {@link RelationType#ALIAS_FOR}{@link RelationType#FORCE_ALIAS_FOR}
* 将目标注解属性包装为{@link AliasedAnnotationAttribute}{@link ForceAliasedAnnotationAttribute}
* 然后用包装后注解属性在对应的合成注解中替换原始的目标注解属性
*
* @param aggregator 合成注解聚合器
* @param annotation {@code originalAttribute}上的{@link Link}注解对象
* @param originalAnnotation 当前正在处理的{@link SynthesizedAnnotation}对象
* @param originalAttribute {@code originalAnnotation}上的待处理的属性
* @param linkedAnnotation {@link Link}指向的关联注解对象
* @param linkedAttribute {@link Link}指向的{@code originalAnnotation}中的关联属性该参数可能为空
*/
@Override
protected void processLinkedAttribute(
SynthesizedAnnotationAggregator aggregator, Link annotation,
SynthesizedAnnotation originalAnnotation, AnnotationAttribute originalAttribute,
SynthesizedAnnotation linkedAnnotation, AnnotationAttribute linkedAttribute) {
// 校验别名关系
checkAliasRelation(annotation, originalAttribute, linkedAttribute);
// 处理aliasFor类型的关系
if (RelationType.ALIAS_FOR.equals(annotation.type())) {
wrappingLinkedAttribute(aggregator, originalAttribute, linkedAttribute, AliasedAnnotationAttribute::new);
return;
}
// 处理forceAliasFor类型的关系
wrappingLinkedAttribute(aggregator, originalAttribute, linkedAttribute, ForceAliasedAnnotationAttribute::new);
}
/**
* 对指定注解属性进行包装若该属性已被包装过则递归以其为根节点的树结构对树上全部的叶子节点进行包装
*/
private void wrappingLinkedAttribute(
SynthesizedAnnotationAggregator synthesizedAnnotationAggregator, AnnotationAttribute originalAttribute, AnnotationAttribute aliasAttribute, BinaryOperator<AnnotationAttribute> wrapping) {
// 不是包装属性
if (!aliasAttribute.isWrapped()) {
processAttribute(synthesizedAnnotationAggregator, originalAttribute, aliasAttribute, wrapping);
return;
}
// 是包装属性
final AbstractWrappedAnnotationAttribute wrapper = (AbstractWrappedAnnotationAttribute)aliasAttribute;
wrapper.getAllLinkedNonWrappedAttributes().forEach(
t -> processAttribute(synthesizedAnnotationAggregator, originalAttribute, t, wrapping)
);
}
/**
* 获取指定注解属性然后将其再进行一层包装
*/
private void processAttribute(
SynthesizedAnnotationAggregator synthesizedAnnotationAggregator, AnnotationAttribute originalAttribute,
AnnotationAttribute target, BinaryOperator<AnnotationAttribute> wrapping) {
Opt.ofNullable(target.getAnnotationType())
.map(synthesizedAnnotationAggregator::getSynthesizedAnnotation)
.ifPresent(t -> t.replaceAttribute(target.getAttributeName(), old -> wrapping.apply(old, originalAttribute)));
}
/**
* 基本校验
*/
private void checkAliasRelation(Link annotation, AnnotationAttribute originalAttribute, AnnotationAttribute linkedAttribute) {
checkLinkedAttributeNotNull(originalAttribute, linkedAttribute, annotation);
checkAttributeType(originalAttribute, linkedAttribute);
checkCircularDependency(originalAttribute, linkedAttribute);
}
/**
* 检查两个属性是否互为别名
*/
private void checkCircularDependency(AnnotationAttribute original, AnnotationAttribute alias) {
checkLinkedSelf(original, alias);
Link annotation = getLinkAnnotation(alias, RelationType.ALIAS_FOR, RelationType.FORCE_ALIAS_FOR);
if (ObjectUtil.isNull(annotation)) {
return;
}
final Class<?> aliasAnnotationType = getLinkedAnnotationType(annotation, alias.getAnnotationType());
if (ObjectUtil.notEqual(aliasAnnotationType, original.getAnnotationType())) {
return;
}
Assert.notEquals(
annotation.attribute(), original.getAttributeName(),
"circular reference between the alias attribute [{}] and the original attribute [{}]",
alias.getAttribute(), original.getAttribute()
);
}
}

View File

@ -5,8 +5,7 @@ package cn.hutool.core.annotation;
* 当别名属性值为默认值时优先返回原属性的值当别名属性不为默认值时优先返回别名属性的值 * 当别名属性值为默认值时优先返回原属性的值当别名属性不为默认值时优先返回别名属性的值
* *
* @author huangchengxing * @author huangchengxing
* @see AliasForLinkAttributePostProcessor * @see AliasLinkAnnotationPostProcessor
* @see RelationType#FORCE_ALIAS_FOR
* @see RelationType#ALIAS_FOR * @see RelationType#ALIAS_FOR
*/ */
public class AliasedAnnotationAttribute extends AbstractWrappedAnnotationAttribute { public class AliasedAnnotationAttribute extends AbstractWrappedAnnotationAttribute {

View File

@ -40,7 +40,7 @@ public class CacheableSynthesizedAnnotationAttributeProcessor implements Synthes
* 越靠前的越优先被取值 * 越靠前的越优先被取值
*/ */
public CacheableSynthesizedAnnotationAttributeProcessor() { public CacheableSynthesizedAnnotationAttributeProcessor() {
this(SyntheticAnnotationUtil.getChildPriorityAnnotationCompare()); this(SynthesizedAnnotation.DEFAULT_CHILD_PRIORITY_COMPARATOR);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")

View File

@ -5,8 +5,8 @@ package cn.hutool.core.annotation;
* 当调用{@link #getValue()}总是返回{@link #linked}的值 * 当调用{@link #getValue()}总是返回{@link #linked}的值
* *
* @author huangchengxing * @author huangchengxing
* @see AliasAttributePostProcessor * @see AliasAnnotationPostProcessor
* @see AliasForLinkAttributePostProcessor * @see AliasLinkAnnotationPostProcessor
* @see RelationType#ALIAS_FOR * @see RelationType#ALIAS_FOR
* @see RelationType#FORCE_ALIAS_FOR * @see RelationType#FORCE_ALIAS_FOR
*/ */

View File

@ -0,0 +1,77 @@
package cn.hutool.core.annotation;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
/**
* <p>用于处理注解对象中带有{@link Link}注解{@link Link#type()}{@link RelationType#MIRROR_FOR}的属性<br>
* 当该处理器执行完毕后原始合成注解中被{@link Link}注解的属性与{@link Link}注解指向的目标注解的属性
* 都将会被被包装并替换为{@link MirroredAnnotationAttribute}
*
* @author huangchengxing
* @see RelationType#MIRROR_FOR
* @see MirroredAnnotationAttribute
*/
public class MirrorLinkAnnotationPostProcessor extends AbstractLinkAnnotationPostProcessor {
private static final RelationType[] PROCESSED_RELATION_TYPES = new RelationType[]{ RelationType.MIRROR_FOR };
@Override
public int order() {
return Integer.MIN_VALUE + 1;
}
/**
* 该处理器只处理{@link Link#type()}类型为{@link RelationType#MIRROR_FOR}的注解属性
*
* @return 仅有{@link RelationType#MIRROR_FOR}数组
*/
@Override
protected RelationType[] processTypes() {
return PROCESSED_RELATION_TYPES;
}
/**
* 将存在镜像关系的合成注解属性分别包装为{@link MirroredAnnotationAttribute}对象
* 并使用包装后{@link MirroredAnnotationAttribute}替换在它们对应合成注解实例中的{@link AnnotationAttribute}
*
* @param aggregator 合成注解聚合器
* @param annotation {@code originalAttribute}上的{@link Link}注解对象
* @param originalAnnotation 当前正在处理的{@link SynthesizedAnnotation}对象
* @param originalAttribute {@code originalAnnotation}上的待处理的属性
* @param linkedAnnotation {@link Link}指向的关联注解对象
* @param linkedAttribute {@link Link}指向的{@code originalAnnotation}中的关联属性该参数可能为空
*/
@Override
protected void processLinkedAttribute(
SynthesizedAnnotationAggregator aggregator, Link annotation,
SynthesizedAnnotation originalAnnotation, AnnotationAttribute originalAttribute,
SynthesizedAnnotation linkedAnnotation, AnnotationAttribute linkedAttribute) {
// 校验镜像关系
checkMirrorRelation(annotation, originalAttribute, linkedAttribute);
// 包装这一对镜像属性并替换原注解中的对应属性
final AnnotationAttribute mirroredOriginalAttribute = new MirroredAnnotationAttribute(originalAttribute, linkedAttribute);
originalAnnotation.setAttribute(originalAttribute.getAttributeName(), mirroredOriginalAttribute);
final AnnotationAttribute mirroredTargetAttribute = new MirroredAnnotationAttribute(linkedAttribute, originalAttribute);
linkedAnnotation.setAttribute(annotation.attribute(), mirroredTargetAttribute);
}
/**
* 基本校验
*/
private void checkMirrorRelation(Link annotation, AnnotationAttribute original, AnnotationAttribute mirror) {
// 镜像属性必须存在
checkLinkedAttributeNotNull(original, mirror, annotation);
// 镜像属性返回值必须一致
checkAttributeType(original, mirror);
// 镜像属性上必须存在对应的注解
final Link mirrorAttributeAnnotation = getLinkAnnotation(mirror, RelationType.MIRROR_FOR);
Assert.isTrue(
ObjectUtil.isNotNull(mirrorAttributeAnnotation) && RelationType.MIRROR_FOR.equals(mirrorAttributeAnnotation.type()),
"mirror attribute [{}] of original attribute [{}] must marked by @Link, and also @LinkType.type() must is [{}]",
mirror.getAttribute(), original.getAttribute(), RelationType.MIRROR_FOR
);
checkLinkedSelf(original, mirror);
}
}

View File

@ -1,71 +0,0 @@
package cn.hutool.core.annotation;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import java.util.HashMap;
import java.util.Map;
/**
* 处理注解中带有{@link Link}注解{@link Link#type()}{@link RelationType#MIRROR_FOR}的属性
*
* @author huangchengxing
* @see MirroredAnnotationAttribute
*/
public class MirrorLinkAttributePostProcessor implements SynthesizedAnnotationPostProcessor {
@Override
public int order() {
return Integer.MIN_VALUE + 1;
}
@Override
public void process(SynthesizedAnnotation annotation, SynthesizedAnnotationAggregator synthesizedAnnotationAggregator) {
Map<String, AnnotationAttribute> attributeMap = new HashMap<>(annotation.getAttributes());
attributeMap.forEach((originalAttributeName, originalAttribute) -> {
// 跳过已经解析的镜像属性
if (originalAttribute instanceof MirroredAnnotationAttribute) {
return;
}
// 获取注解
final Link link = SyntheticAnnotationUtil.getLink(originalAttribute, RelationType.MIRROR_FOR);
if (ObjectUtil.isNull(link)) {
return;
}
// 获取指定镜像属性所在的注解
final SynthesizedAnnotation mirrorAnnotation = SyntheticAnnotationUtil.getLinkedAnnotation(link, synthesizedAnnotationAggregator, annotation.annotationType());
if (ObjectUtil.isNull(mirrorAnnotation)) {
return;
}
// 获取镜像属性并进行校验
final AnnotationAttribute mirrorAttribute = mirrorAnnotation.getAttributes().get(link.attribute());
checkMirrorRelation(link, originalAttribute, mirrorAttribute);
// 包装这一对镜像属性并替换原注解中的对应属性
final AnnotationAttribute mirroredOriginalAttribute = new MirroredAnnotationAttribute(originalAttribute, mirrorAttribute);
synthesizedAnnotationAggregator.getSynthesizedAnnotation(originalAttribute.getAnnotationType())
.setAttribute(originalAttributeName, mirroredOriginalAttribute);
final AnnotationAttribute mirroredTargetAttribute = new MirroredAnnotationAttribute(mirrorAttribute, originalAttribute);
mirrorAnnotation.setAttribute(link.attribute(), mirroredTargetAttribute);
});
}
private void checkMirrorRelation(Link annotation, AnnotationAttribute original, AnnotationAttribute mirror) {
// 镜像属性必须存在
SyntheticAnnotationUtil.checkLinkedAttributeNotNull(original, mirror, annotation);
// 镜像属性返回值必须一致
SyntheticAnnotationUtil.checkAttributeType(original, mirror);
// 镜像属性上必须存在对应的注解
final Link mirrorAttributeAnnotation = SyntheticAnnotationUtil.getLink(mirror, RelationType.MIRROR_FOR);
Assert.isTrue(
ObjectUtil.isNotNull(mirrorAttributeAnnotation) && RelationType.MIRROR_FOR.equals(mirrorAttributeAnnotation.type()),
"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);
}
}

View File

@ -6,7 +6,7 @@ import cn.hutool.core.lang.Assert;
* 表示存在对应镜像属性的注解属性当获取值时将根据{@link RelationType#MIRROR_FOR}的规则进行处理 * 表示存在对应镜像属性的注解属性当获取值时将根据{@link RelationType#MIRROR_FOR}的规则进行处理
* *
* @author huangchengxing * @author huangchengxing
* @see MirrorLinkAttributePostProcessor * @see MirrorLinkAnnotationPostProcessor
* @see RelationType#MIRROR_FOR * @see RelationType#MIRROR_FOR
*/ */
public class MirroredAnnotationAttribute extends AbstractWrappedAnnotationAttribute { public class MirroredAnnotationAttribute extends AbstractWrappedAnnotationAttribute {

View File

@ -3,15 +3,15 @@ package cn.hutool.core.annotation;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
import java.util.Comparator;
import java.util.Map; import java.util.Map;
import java.util.function.UnaryOperator; import java.util.function.UnaryOperator;
/** /**
* <p>用于在{@link SynthesizedAnnotationAggregator}中表示一个处于合成状态的注解对象<br> * <p>用于在{@link SynthesizedAnnotationAggregator}中表示一个处于合成状态的注解对象<br>
* 当对多个合成注解排序时默认先按{@link #getVerticalDistance()}排序 * 当对多个合成注解排序时默认使用{@link #DEFAULT_CHILD_PRIORITY_COMPARATOR}进行排序
* 再按{@link #getHorizontalDistance()}排序 * 从保证合成注解按{@link #getVerticalDistance()}{@link #getHorizontalDistance()}的返回值保持有序
* 该顺序应当保证当合成注解与其他注解存在层级关系时 * 从而使得距离根元素更接近的注解对象在被处理是具有更高的优先级
* 离根对象最接近的注解被排在靠前的位置
* *
* @author huangchengxing * @author huangchengxing
* @see SynthesizedAnnotationAggregator * @see SynthesizedAnnotationAggregator
@ -19,7 +19,16 @@ import java.util.function.UnaryOperator;
public interface SynthesizedAnnotation extends Annotation, Comparable<SynthesizedAnnotation> { public interface SynthesizedAnnotation extends Annotation, Comparable<SynthesizedAnnotation> {
/** /**
* 获取所属的合成注解 * {@link SynthesizedAnnotation}使用的默认的比较器
* 按照按{@link #getVerticalDistance()}{@link #getHorizontalDistance()}的返回值进行排序<br>
* 一般情况下排序越小的合成注解应当被优先处理
*/
Comparator<SynthesizedAnnotation> DEFAULT_CHILD_PRIORITY_COMPARATOR = Comparator
.comparing(SynthesizedAnnotation::getVerticalDistance)
.thenComparing(SynthesizedAnnotation::getHorizontalDistance);
/**
* 获取所属的合成注解聚合器
* *
* @return 合成注解 * @return 合成注解
*/ */
@ -114,7 +123,7 @@ public interface SynthesizedAnnotation extends Annotation, Comparable<Synthesize
*/ */
@Override @Override
default int compareTo(SynthesizedAnnotation o) { default int compareTo(SynthesizedAnnotation o) {
return SyntheticAnnotationUtil.getChildPriorityAnnotationCompare().compare(this, o); return DEFAULT_CHILD_PRIORITY_COMPARATOR.compare(this, o);
} }
} }

View File

@ -12,16 +12,16 @@ import java.util.Comparator;
* *
* <p>该接口存在多个实现类调用者应当保证在任何时候对一批后置处理器的调用顺序都符合 * <p>该接口存在多个实现类调用者应当保证在任何时候对一批后置处理器的调用顺序都符合
* <ul> * <ul>
* <li>{@link AliasAttributePostProcessor}</li> * <li>{@link AliasAnnotationPostProcessor}</li>
* <li>{@link MirrorLinkAttributePostProcessor}</li> * <li>{@link MirrorLinkAnnotationPostProcessor}</li>
* <li>{@link AliasForLinkAttributePostProcessor}</li> * <li>{@link AliasLinkAnnotationPostProcessor}</li>
* <li>其他后置处理器</li> * <li>其他后置处理器</li>
* </ul> * </ul>
* *
* @author huangchengxing * @author huangchengxing
* @see AliasAttributePostProcessor * @see AliasAnnotationPostProcessor
* @see MirrorLinkAttributePostProcessor * @see MirrorLinkAnnotationPostProcessor
* @see AliasForLinkAttributePostProcessor * @see AliasLinkAnnotationPostProcessor
*/ */
public interface SynthesizedAnnotationPostProcessor extends Comparable<SynthesizedAnnotationPostProcessor> { public interface SynthesizedAnnotationPostProcessor extends Comparable<SynthesizedAnnotationPostProcessor> {
@ -46,11 +46,11 @@ public interface SynthesizedAnnotationPostProcessor extends Comparable<Synthesiz
} }
/** /**
* 给定指定被合成注解与其所属的合成注解实例经过处理后返回最终 * 给定指定被合成注解与其所属的合成注解聚合器实例经过处理后返回最终
* *
* @param annotation 合成的注解 * @param synthesizedAnnotation 合成的注解
* @param synthesizedAnnotationAggregator 注解所属的合成注解 * @param aggregator 合成注解聚合器
*/ */
void process(SynthesizedAnnotation annotation, SynthesizedAnnotationAggregator synthesizedAnnotationAggregator); void process(SynthesizedAnnotation synthesizedAnnotation, SynthesizedAnnotationAggregator aggregator);
} }

View File

@ -3,16 +3,11 @@ package cn.hutool.core.annotation;
import cn.hutool.core.annotation.scanner.MetaAnnotationScanner; import cn.hutool.core.annotation.scanner.MetaAnnotationScanner;
import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Opt; import cn.hutool.core.lang.Opt;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement; import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.util.*; import java.util.*;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/** /**
* {@link SynthesizedAnnotationAggregator}的基本实现表示一个根注解与根注解上的多层元注解的聚合状态 * {@link SynthesizedAnnotationAggregator}的基本实现表示一个根注解与根注解上的多层元注解的聚合状态
@ -29,13 +24,13 @@ import java.util.stream.Stream;
* 此时若出现扫描时得到了多个同类型的注解对象有且仅有最接近根注解的注解对象会被作为有效注解 * 此时若出现扫描时得到了多个同类型的注解对象有且仅有最接近根注解的注解对象会被作为有效注解
* *
* <p>当扫描的注解对象经过{@link SynthesizedAnnotationSelector}处理后 * <p>当扫描的注解对象经过{@link SynthesizedAnnotationSelector}处理后
* 将会被转为{@link MetaAnnotation}并使用在实例化时指定的{@link AliasAttributePostProcessor} * 将会被转为{@link MetaAnnotation}并使用在实例化时指定的{@link AliasAnnotationPostProcessor}
* 进行后置处理<br> * 进行后置处理<br>
* 默认情况下将注册以下后置处理器以对{@link Alias}{@link Link}和其扩展注解提供支持 * 默认情况下将注册以下后置处理器以对{@link Alias}{@link Link}和其扩展注解提供支持
* <ul> * <ul>
* <li>{@link AliasAttributePostProcessor}</li> * <li>{@link AliasAnnotationPostProcessor}</li>
* <li>{@link MirrorLinkAttributePostProcessor}</li> * <li>{@link MirrorLinkAnnotationPostProcessor}</li>
* <li>{@link AliasForLinkAttributePostProcessor}</li> * <li>{@link AliasLinkAnnotationPostProcessor}</li>
* </ul> * </ul>
* 若用户需要自行扩展则需要保证上述三个处理器被正确注入当前实例 * 若用户需要自行扩展则需要保证上述三个处理器被正确注入当前实例
* *
@ -89,9 +84,9 @@ public class SynthesizedMetaAnnotationAggregator implements SynthesizedAnnotatio
source, SynthesizedAnnotationSelector.NEAREST_AND_OLDEST_PRIORITY, source, SynthesizedAnnotationSelector.NEAREST_AND_OLDEST_PRIORITY,
new CacheableSynthesizedAnnotationAttributeProcessor(), new CacheableSynthesizedAnnotationAttributeProcessor(),
Arrays.asList( Arrays.asList(
new AliasAttributePostProcessor(), new AliasAnnotationPostProcessor(),
new MirrorLinkAttributePostProcessor(), new MirrorLinkAnnotationPostProcessor(),
new AliasForLinkAttributePostProcessor() new AliasLinkAnnotationPostProcessor()
) )
); );
} }
@ -284,160 +279,23 @@ public class SynthesizedMetaAnnotationAggregator implements SynthesizedAnnotatio
} }
/** /**
* 注解包装类 * 注解包装类表示{@link #source}以及{@link #source}所属层级结构中的全部关联注解对象
* *
* @author huangchengxing * @author huangchengxing
*/ */
public static class MetaAnnotation implements Annotation, SynthesizedAnnotation { public static class MetaAnnotation extends AbstractSynthesizedAnnotation<Annotation> {
private final SynthesizedAnnotationAggregator owner;
private final Annotation root;
private final Annotation annotation;
private final Map<String, AnnotationAttribute> attributeMethodCaches;
private final int verticalDistance;
private final int horizontalDistance;
public MetaAnnotation(SynthesizedAnnotationAggregator owner, Annotation root, Annotation annotation, int verticalDistance, int horizontalDistance) {
this.owner = owner;
this.root = root;
this.annotation = annotation;
this.verticalDistance = verticalDistance;
this.horizontalDistance = horizontalDistance;
this.attributeMethodCaches = Stream.of(annotation.annotationType().getDeclaredMethods())
.filter(AnnotationUtil::isAttributeMethod)
.collect(Collectors.toMap(Method::getName, method -> new CacheableAnnotationAttribute(annotation, method)));
}
/** /**
* 获取所属的合成注解 * 创建一个合成注解
* *
* @return 合成注解 * @param owner 合成注解所属的合成注解聚合器
* @param root 根对象
* @param annotation 被合成的注解对象
* @param verticalDistance 距离根对象的水平距离
* @param horizontalDistance 距离根对象的垂直距离
*/ */
@Override protected MetaAnnotation(SynthesizedAnnotationAggregator owner, Annotation root, Annotation annotation, int verticalDistance, int horizontalDistance) {
public SynthesizedAnnotationAggregator getOwner() { super(owner, root, annotation, verticalDistance, horizontalDistance);
return owner;
}
/**
* 获取注解类型
*
* @return 注解类型
*/
@Override
public Class<? extends Annotation> annotationType() {
return annotation.annotationType();
}
/**
* 获取根注解
*
* @return 根注解
*/
@Override
public Annotation getRoot() {
return this.root;
}
/**
* 获取元注解
*
* @return 元注解
*/
@Override
public Annotation getAnnotation() {
return annotation;
}
/**
* 获取该合成注解与根注解之间相隔的层级数
*
* @return 该合成注解与根注解之间相隔的层级数
*/
@Override
public int getVerticalDistance() {
return verticalDistance;
}
/**
* 获取该合成注解与根注解之间相隔的注解树
*
* @return 该合成注解与根注解之间相隔的注解树
*/
@Override
public int getHorizontalDistance() {
return horizontalDistance;
}
/**
* 元注解是否存在该属性
*
* @param attributeName 属性名
* @return 是否存在该属性
*/
public boolean hasAttribute(String attributeName) {
return attributeMethodCaches.containsKey(attributeName);
}
/**
* 元注解是否存在该属性且该属性的值类型是指定类型或其子类
*
* @param attributeName 属性名
* @param returnType 返回值类型
* @return 是否存在该属性
*/
@Override
public boolean hasAttribute(String attributeName, Class<?> returnType) {
return Opt.ofNullable(attributeMethodCaches.get(attributeName))
.filter(method -> ClassUtil.isAssignable(returnType, method.getAttributeType()))
.isPresent();
}
/**
* 获取该注解的全部属性
*
* @return 注解属性
*/
@Override
public Map<String, AnnotationAttribute> getAttributes() {
return this.attributeMethodCaches;
}
/**
* 设置属性值
*
* @param attributeName 属性名称
* @param attribute 注解属性
*/
@Override
public void setAttribute(String attributeName, AnnotationAttribute attribute) {
attributeMethodCaches.put(attributeName, attribute);
}
/**
* 替换属性值
*
* @param attributeName 属性名
* @param operator 替换操作
*/
@Override
public void replaceAttribute(String attributeName, UnaryOperator<AnnotationAttribute> operator) {
AnnotationAttribute old = attributeMethodCaches.get(attributeName);
if (ObjectUtil.isNotNull(old)) {
attributeMethodCaches.put(attributeName, operator.apply(old));
}
}
/**
* 获取属性值
*
* @param attributeName 属性名
* @return 属性值
*/
@Override
public Object getAttributeValue(String attributeName) {
return Opt.ofNullable(attributeMethodCaches.get(attributeName))
.map(AnnotationAttribute::getValue)
.get();
} }
} }

View File

@ -80,7 +80,7 @@ class SyntheticAnnotationProxy implements InvocationHandler {
void loadMethods() { void loadMethods() {
methods.put("toString", (method, args) -> proxyToString()); methods.put("toString", (method, args) -> proxyToString());
methods.put("hashCode", (method, args) -> proxyHashCode()); methods.put("hashCode", (method, args) -> proxyHashCode());
methods.put("getSynthesizedAnnotation", (method, args) -> proxyGetSyntheticAnnotation()); methods.put("getSynthesizedAnnotationAggregator", (method, args) -> proxyGetSynthesizedAnnotationAggregator());
methods.put("getSynthesizedAnnotation", (method, args) -> proxyGetSynthesizedAnnotation()); methods.put("getSynthesizedAnnotation", (method, args) -> proxyGetSynthesizedAnnotation());
methods.put("getRoot", (method, args) -> annotation.getRoot()); methods.put("getRoot", (method, args) -> annotation.getRoot());
methods.put("getVerticalDistance", (method, args) -> annotation.getVerticalDistance()); methods.put("getVerticalDistance", (method, args) -> annotation.getVerticalDistance());
@ -110,7 +110,7 @@ class SyntheticAnnotationProxy implements InvocationHandler {
return Objects.hash(annotation.getOwner(), annotation); return Objects.hash(annotation.getOwner(), annotation);
} }
private Object proxyGetSyntheticAnnotation() { private Object proxyGetSynthesizedAnnotationAggregator() {
return annotation.getOwner(); return annotation.getOwner();
} }
@ -134,7 +134,7 @@ class SyntheticAnnotationProxy implements InvocationHandler {
* *
* @return 合成注解 * @return 合成注解
*/ */
SynthesizedAnnotationAggregator getSyntheticAnnotation(); SynthesizedAnnotationAggregator getSynthesizedAnnotationAggregator();
/** /**
* 获取该代理注解对应的已合成注解 * 获取该代理注解对应的已合成注解

View File

@ -1,106 +0,0 @@
package cn.hutool.core.annotation;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import java.lang.annotation.Annotation;
import java.util.Comparator;
/**
* {@link SynthesizedAnnotationAggregator}相关工具用于内部使用
*
* @author huangchengxing
*/
class SyntheticAnnotationUtil {
/**
* 从注解属性上获取指定类型的{@link Link}注解
*
* @param attribute 注解属性
* @param relationTypes 类型
* @return 注解
*/
static Link getLink(AnnotationAttribute attribute, RelationType... relationTypes) {
return Opt.ofNullable(attribute)
.map(t -> AnnotationUtil.getSynthesizedAnnotation(attribute.getAttribute(), Link.class))
.filter(a -> ArrayUtil.contains(relationTypes, a.type()))
.get();
}
/**
* 从合成注解中获取{@link Link#type()}指定的注解对象
*
* @param annotation {@link Link}注解
* @param synthesizedAnnotationAggregator 合成注解
*/
static SynthesizedAnnotation getLinkedAnnotation(
Link annotation, SynthesizedAnnotationAggregator synthesizedAnnotationAggregator, Class<? extends Annotation> defaultType) {
final Class<?> targetAnnotationType = getLinkedAnnotationType(annotation, defaultType);
return synthesizedAnnotationAggregator.getSynthesizedAnnotation(targetAnnotationType);
}
/**
* {@link Link#annotation()}获取的类型{@link Annotation#getClass()}则返回{@code defaultType}
* 否则返回{@link Link#annotation()}指定的类型
*
* @param annotation {@link Link}注解
* @param defaultType 默认注解类型
* @return 注解类型
*/
static Class<?> getLinkedAnnotationType(Link annotation, Class<?> defaultType) {
return ObjectUtil.equals(annotation.annotation(), Annotation.class) ?
defaultType : annotation.annotation();
}
/**
* 校验两个注解属性的返回值类型是否一致
*
* @param original 原属性
* @param alias 别名属性
*/
static void checkAttributeType(AnnotationAttribute original, AnnotationAttribute alias) {
Assert.equals(
original.getAttributeType(), alias.getAttributeType(),
"return type of the linked attribute [{}] is inconsistent with the original [{}]",
original.getAttribute(), alias.getAttribute()
);
}
/**
* 检查{@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}指向的注解属性是否存在
*
* @param original {@link Link}注解的属性
* @param linkedAttribute {@link Link}指向的注解属性
* @param annotation {@link Link}注解
*/
static void checkLinkedAttributeNotNull(AnnotationAttribute original, AnnotationAttribute linkedAttribute, Link annotation) {
Assert.notNull(linkedAttribute, "cannot find linked attribute [{}] of original [{}] in [{}]",
original.getAttribute(), annotation.attribute(),
getLinkedAnnotationType(annotation, original.getAnnotationType())
);
}
/**
* 获取按{@link SynthesizedAnnotation#getVerticalDistance()}{@link SynthesizedAnnotation#getHorizontalDistance()}排序的比较器
*
* @return 比较值
*/
static Comparator<SynthesizedAnnotation> getChildPriorityAnnotationCompare() {
return Comparator.comparing(SynthesizedAnnotation::getVerticalDistance)
.thenComparing(SynthesizedAnnotation::getHorizontalDistance);
}
}

View File

@ -12,11 +12,11 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.function.UnaryOperator; import java.util.function.UnaryOperator;
public class AliasAttributePostProcessorTest { public class AliasAnnotationPostProcessorTest {
@Test @Test
public void processTest() { public void processTest() {
AliasAttributePostProcessor processor = new AliasAttributePostProcessor(); AliasAnnotationPostProcessor processor = new AliasAnnotationPostProcessor();
Map<Class<?>, SynthesizedAnnotation> annotationMap = new HashMap<>(); Map<Class<?>, SynthesizedAnnotation> annotationMap = new HashMap<>();
SynthesizedAnnotationAggregator synthesizedAnnotationAggregator = new TestSynthesizedAnnotationAggregator(annotationMap); SynthesizedAnnotationAggregator synthesizedAnnotationAggregator = new TestSynthesizedAnnotationAggregator(annotationMap);

View File

@ -12,11 +12,11 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.function.UnaryOperator; import java.util.function.UnaryOperator;
public class AliasForLinkAttributePostProcessorTest { public class AliasLinkAnnotationPostProcessorTest {
@Test @Test
public void processForceAliasForTest() { public void processForceAliasForTest() {
AliasForLinkAttributePostProcessor processor = new AliasForLinkAttributePostProcessor(); AliasLinkAnnotationPostProcessor processor = new AliasLinkAnnotationPostProcessor();
Map<Class<?>, SynthesizedAnnotation> annotationMap = new HashMap<>(); Map<Class<?>, SynthesizedAnnotation> annotationMap = new HashMap<>();
SynthesizedAnnotationAggregator synthesizedAnnotationAggregator = new TestSynthesizedAnnotationAggregator(annotationMap); SynthesizedAnnotationAggregator synthesizedAnnotationAggregator = new TestSynthesizedAnnotationAggregator(annotationMap);
@ -40,7 +40,7 @@ public class AliasForLinkAttributePostProcessorTest {
@Test @Test
public void processAliasForTest() { public void processAliasForTest() {
AliasForLinkAttributePostProcessor processor = new AliasForLinkAttributePostProcessor(); AliasLinkAnnotationPostProcessor processor = new AliasLinkAnnotationPostProcessor();
Map<Class<?>, SynthesizedAnnotation> annotationMap = new HashMap<>(); Map<Class<?>, SynthesizedAnnotation> annotationMap = new HashMap<>();
SynthesizedAnnotationAggregator synthesizedAnnotationAggregator = new TestSynthesizedAnnotationAggregator(annotationMap); SynthesizedAnnotationAggregator synthesizedAnnotationAggregator = new TestSynthesizedAnnotationAggregator(annotationMap);

View File

@ -12,11 +12,11 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.function.UnaryOperator; import java.util.function.UnaryOperator;
public class MirrorLinkAttributePostProcessorTest { public class MirrorLinkAnnotationPostProcessorTest {
@Test @Test
public void processTest() { public void processTest() {
MirrorLinkAttributePostProcessor processor = new MirrorLinkAttributePostProcessor(); MirrorLinkAnnotationPostProcessor processor = new MirrorLinkAnnotationPostProcessor();
Map<Class<?>, SynthesizedAnnotation> annotationMap = new HashMap<>(); Map<Class<?>, SynthesizedAnnotation> annotationMap = new HashMap<>();
SynthesizedAnnotationAggregator synthesizedAnnotationAggregator = new TestSynthesizedAnnotationAggregator(annotationMap); SynthesizedAnnotationAggregator synthesizedAnnotationAggregator = new TestSynthesizedAnnotationAggregator(annotationMap);

View File

@ -36,7 +36,7 @@ public class TypeAnnotationScannerTest {
annotations.forEach(a -> Assert.assertEquals(a.annotationType(), AnnotationForScannerTest.class)); annotations.forEach(a -> Assert.assertEquals(a.annotationType(), AnnotationForScannerTest.class));
// 不查找父类 // 不查找父类
scanner = new TypeAnnotationScanner().setIncludeSupperClass(false); scanner = new TypeAnnotationScanner().setIncludeSuperClass(false);
annotations = scanner.getAnnotations(Example.class); annotations = scanner.getAnnotations(Example.class);
Assert.assertEquals(1, annotations.size()); Assert.assertEquals(1, annotations.size());
annotations.forEach(a -> Assert.assertEquals(a.annotationType(), AnnotationForScannerTest.class)); annotations.forEach(a -> Assert.assertEquals(a.annotationType(), AnnotationForScannerTest.class));
@ -88,7 +88,7 @@ public class TypeAnnotationScannerTest {
// 不查找父类 // 不查找父类
map.clear(); map.clear();
new TypeAnnotationScanner() new TypeAnnotationScanner()
.setIncludeSupperClass(false) .setIncludeSuperClass(false)
.scan( .scan(
(index, annotation) -> map.computeIfAbsent(index, i -> new ArrayList<>()).add(annotation), (index, annotation) -> map.computeIfAbsent(index, i -> new ArrayList<>()).add(annotation),
Example.class, null Example.class, null