Commit 45cda665 authored by ma yanling's avatar ma yanling
Browse files

project commit

parent ad2fb30a
Pipeline #2354 failed with stages
in 0 seconds
package cn.hutool.core.annotation;
import java.lang.annotation.*;
/**
* <p>{@link Link}的子注解。表示“原始属性”将强制作为“关联属性”的别名。效果等同于在“原始属性”上添加{@link Alias}注解,
* 任何情况下,获取“关联属性”的值都将直接返回“原始属性”的值
* <b>注意,该注解与{@link Link}、{@link AliasFor}或{@link MirrorFor}一起使用时,将只有被声明在最上面的注解会生效</b>
*
* @author huangchengxing
* @see Link
* @see RelationType#FORCE_ALIAS_FOR
*/
@Link(type = RelationType.FORCE_ALIAS_FOR)
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
public @interface ForceAliasFor {
/**
* 产生关联的注解类型,当不指定时,默认指注释的属性所在的类
*
* @return 关联注解类型
*/
@Link(annotation = Link.class, attribute = "annotation", type = RelationType.FORCE_ALIAS_FOR)
Class<? extends Annotation> annotation() default Annotation.class;
/**
* {@link #annotation()}指定注解中关联的属性
*
* @return 关联的属性
*/
@Link(annotation = Link.class, attribute = "attribute", type = RelationType.FORCE_ALIAS_FOR)
String attribute() default "";
}
package cn.hutool.core.annotation;
/**
* 表示一个被指定了强制别名的注解属性。
* 当调用{@link #getValue()}时,总是返回{@link #linked}的值
*
* @author huangchengxing
* @see AliasAnnotationPostProcessor
* @see AliasLinkAnnotationPostProcessor
* @see RelationType#ALIAS_FOR
* @see RelationType#FORCE_ALIAS_FOR
*/
public class ForceAliasedAnnotationAttribute extends AbstractWrappedAnnotationAttribute {
protected ForceAliasedAnnotationAttribute(AnnotationAttribute origin, AnnotationAttribute linked) {
super(origin, linked);
}
/**
* 总是返回{@link #linked}的{@link AnnotationAttribute#getValue()}的返回值
*
* @return {@link #linked}的{@link AnnotationAttribute#getValue()}的返回值
*/
@Override
public Object getValue() {
return linked.getValue();
}
/**
* 总是返回{@link #linked}的{@link AnnotationAttribute#isValueEquivalentToDefaultValue()}的返回值
*
* @return {@link #linked}的{@link AnnotationAttribute#isValueEquivalentToDefaultValue()}的返回值
*/
@Override
public boolean isValueEquivalentToDefaultValue() {
return linked.isValueEquivalentToDefaultValue();
}
/**
* 总是返回{@link #linked}的{@link AnnotationAttribute#getAttributeType()}的返回值
*
* @return {@link #linked}的{@link AnnotationAttribute#getAttributeType()}的返回值
*/
@Override
public Class<?> getAttributeType() {
return linked.getAttributeType();
}
}
package cn.hutool.core.annotation;
import cn.hutool.core.annotation.scanner.AnnotationScanner;
import cn.hutool.core.annotation.scanner.MetaAnnotationScanner;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.util.ObjectUtil;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.util.*;
/**
* {@link SynthesizedAggregateAnnotation}的基本实现,表示基于多个注解对象,
* 或多个根注解对象与他们的多层元注解对象的聚合得到的注解。
*
* <p>假设现有注解A,若指定的{@link #annotationScanner}支持扫描注解A的元注解,
* 且A上存在元注解B,B上存在元注解C,则对注解A进行解析,将得到包含根注解A,以及其元注解B、C在内的合成元注解聚合{@link GenericSynthesizedAggregateAnnotation}。
* 从{@link AnnotatedElement}的角度来说,得到的合成注解是一个同时承载有ABC三个注解对象的被注解元素,
* 因此通过调用{@link AnnotatedElement}的相关方法将返回对应符合语义的注解对象。
*
* <p>在扫描指定根注解及其元注解时,若在不同的层级出现了类型相同的注解实例,
* 将会根据实例化时指定的{@link SynthesizedAnnotationSelector}选择最优的注解,
* 完成对根注解及其元注解的扫描后,合成注解中每种类型的注解对象都将有且仅有一个。<br>
* 默认情况下,将使用{@link SynthesizedAnnotationSelector#NEAREST_AND_OLDEST_PRIORITY}作为选择器,
* 此时若出现扫描时得到了多个同类型的注解对象,有且仅有最接近根注解的注解对象会被作为有效注解。
*
* <p>当扫描的注解对象经过{@link SynthesizedAnnotationSelector}处理后,
* 将会被转为{@link MetaAnnotation},并使用在实例化时指定的{@link AliasAnnotationPostProcessor}
* 进行后置处理。<br>
* 默认情况下,将注册以下后置处理器以对{@link Alias}与{@link Link}和其扩展注解提供支持:
* <ul>
* <li>{@link AliasAnnotationPostProcessor};</li>
* <li>{@link MirrorLinkAnnotationPostProcessor};</li>
* <li>{@link AliasLinkAnnotationPostProcessor};</li>
* </ul>
* 若用户需要自行扩展,则需要保证上述三个处理器被正确注入当前实例。
*
* <p>{@link GenericSynthesizedAggregateAnnotation}支持通过{@link #getAttributeValue(String, Class)},
* 或通过{@link #synthesize(Class)}获得注解代理对象后获取指定类型的注解属性值,
* 返回的属性值将根据合成注解中对应原始注解属性上的{@link Alias}与{@link Link}注解而有所变化。
* 通过当前实例获取属性值时,将经过{@link SynthesizedAnnotationAttributeProcessor}的处理。<br>
* 默认情况下,实例将会注册{@link CacheableSynthesizedAnnotationAttributeProcessor},
* 该处理器将令元注解中与子注解类型与名称皆一致的属性被子注解的属性覆盖,并且缓存最终获取到的属性值。
*
* @author huangchengxing
* @see AnnotationUtil
* @see SynthesizedAnnotationProxy
* @see SynthesizedAnnotationSelector
* @see SynthesizedAnnotationAttributeProcessor
* @see SynthesizedAnnotationPostProcessor
* @see AnnotationSynthesizer
* @see AnnotationScanner
*/
public class GenericSynthesizedAggregateAnnotation
extends AbstractAnnotationSynthesizer<List<Annotation>>
implements SynthesizedAggregateAnnotation {
/**
* 根对象
*/
private final Object root;
/**
* 距离根对象的垂直距离
*/
private final int verticalDistance;
/**
* 距离根对象的水平距离
*/
private final int horizontalDistance;
/**
* 合成注解属性处理器
*/
private final SynthesizedAnnotationAttributeProcessor attributeProcessor;
/**
* 基于指定根注解,为其与其元注解的层级结构中的全部注解构造一个合成注解。
* 当层级结构中出现了相同的注解对象时,将优先选择以距离根注解最近,且优先被扫描的注解对象,
* 当获取值时,同样遵循该规则。
*
* @param source 源注解
*/
public GenericSynthesizedAggregateAnnotation(Annotation... source) {
this(Arrays.asList(source), new MetaAnnotationScanner());
}
/**
* 基于指定根注解,为其层级结构中的全部注解构造一个合成注解。
* 若扫描器支持对注解的层级结构进行扫描,则若层级结构中出现了相同的注解对象时,
* 将优先选择以距离根注解最近,且优先被扫描的注解对象,并且当获取注解属性值时同样遵循该规则。
*
* @param source 源注解
* @param annotationScanner 注解扫描器,该扫描器必须支持扫描注解类
*/
public GenericSynthesizedAggregateAnnotation(List<Annotation> source, AnnotationScanner annotationScanner) {
this(
source, SynthesizedAnnotationSelector.NEAREST_AND_OLDEST_PRIORITY,
new CacheableSynthesizedAnnotationAttributeProcessor(),
Arrays.asList(
SynthesizedAnnotationPostProcessor.ALIAS_ANNOTATION_POST_PROCESSOR,
SynthesizedAnnotationPostProcessor.MIRROR_LINK_ANNOTATION_POST_PROCESSOR,
SynthesizedAnnotationPostProcessor.ALIAS_LINK_ANNOTATION_POST_PROCESSOR
),
annotationScanner
);
}
/**
* 基于指定根注解,为其层级结构中的全部注解构造一个合成注解
*
* @param source 当前查找的注解对象
* @param annotationSelector 合成注解选择器
* @param attributeProcessor 注解属性处理器
* @param annotationPostProcessors 注解后置处理器
* @param annotationScanner 注解扫描器,该扫描器必须支持扫描注解类
*/
public GenericSynthesizedAggregateAnnotation(
List<Annotation> source,
SynthesizedAnnotationSelector annotationSelector,
SynthesizedAnnotationAttributeProcessor attributeProcessor,
Collection<SynthesizedAnnotationPostProcessor> annotationPostProcessors,
AnnotationScanner annotationScanner) {
this(
null, 0, 0,
source, annotationSelector, attributeProcessor, annotationPostProcessors, annotationScanner
);
}
/**
* 基于指定根注解,为其层级结构中的全部注解构造一个合成注解
*
* @param root 根对象
* @param verticalDistance 距离根对象的水平距离
* @param horizontalDistance 距离根对象的垂直距离
* @param source 当前查找的注解对象
* @param annotationSelector 合成注解选择器
* @param attributeProcessor 注解属性处理器
* @param annotationPostProcessors 注解后置处理器
* @param annotationScanner 注解扫描器,该扫描器必须支持扫描注解类
*/
GenericSynthesizedAggregateAnnotation(
Object root, int verticalDistance, int horizontalDistance,
List<Annotation> source,
SynthesizedAnnotationSelector annotationSelector,
SynthesizedAnnotationAttributeProcessor attributeProcessor,
Collection<SynthesizedAnnotationPostProcessor> annotationPostProcessors,
AnnotationScanner annotationScanner) {
super(source, annotationSelector, annotationPostProcessors, annotationScanner);
Assert.notNull(attributeProcessor, "attributeProcessor must not null");
this.root = ObjectUtil.defaultIfNull(root, this);
this.verticalDistance = verticalDistance;
this.horizontalDistance = horizontalDistance;
this.attributeProcessor = attributeProcessor;
}
/**
* 获取根对象
*
* @return 根对象
*/
@Override
public Object getRoot() {
return root;
}
/**
* 获取与根对象的垂直距离
*
* @return 与根对象的垂直距离
*/
@Override
public int getVerticalDistance() {
return verticalDistance;
}
/**
* 获取与根对象的水平距离
*
* @return 获取与根对象的水平距离
*/
@Override
public int getHorizontalDistance() {
return horizontalDistance;
}
/**
* 按广度优先扫描{@link #source}上的元注解
*/
@Override
protected Map<Class<? extends Annotation>, SynthesizedAnnotation> loadAnnotations() {
Map<Class<? extends Annotation>, SynthesizedAnnotation> annotationMap = new LinkedHashMap<>();
// 根注解默认水平坐标为0,根注解的元注解坐标从1开始
for (int i = 0; i < source.size(); i++) {
final Annotation sourceAnnotation = source.get(i);
Assert.isFalse(AnnotationUtil.isSynthesizedAnnotation(sourceAnnotation), "source [{}] has been synthesized");
annotationMap.put(sourceAnnotation.annotationType(), new MetaAnnotation(sourceAnnotation, sourceAnnotation, 0, i));
Assert.isTrue(
annotationScanner.support(sourceAnnotation.annotationType()),
"annotation scanner [{}] cannot support scan [{}]",
annotationScanner, sourceAnnotation.annotationType()
);
annotationScanner.scan(
(index, annotation) -> {
SynthesizedAnnotation oldAnnotation = annotationMap.get(annotation.annotationType());
SynthesizedAnnotation newAnnotation = new MetaAnnotation(sourceAnnotation, annotation, index + 1, annotationMap.size());
if (ObjectUtil.isNull(oldAnnotation)) {
annotationMap.put(annotation.annotationType(), newAnnotation);
} else {
annotationMap.put(annotation.annotationType(), annotationSelector.choose(oldAnnotation, newAnnotation));
}
},
sourceAnnotation.annotationType(), null
);
}
return annotationMap;
}
/**
* 获取合成注解属性处理器
*
* @return 合成注解属性处理器
*/
@Override
public SynthesizedAnnotationAttributeProcessor getAnnotationAttributeProcessor() {
return this.attributeProcessor;
}
/**
* 根据指定的属性名与属性类型获取对应的属性值,若存在{@link Alias}则获取{@link Alias#value()}指定的别名属性的值
* <p>当不同层级的注解之间存在同名同类型属性时,将优先获取更接近根注解的属性
*
* @param attributeName 属性名
* @param attributeType 属性类型
* @return 属性
*/
@Override
public Object getAttributeValue(String attributeName, Class<?> attributeType) {
return attributeProcessor.getAttributeValue(attributeName, attributeType, synthesizedAnnotationMap.values());
}
/**
* 获取合成注解中包含的指定注解
*
* @param annotationType 注解类型
* @param <T> 注解类型
* @return 注解对象
*/
@Override
public <T extends Annotation> T getAnnotation(Class<T> annotationType) {
return Opt.ofNullable(annotationType)
.map(synthesizedAnnotationMap::get)
.map(SynthesizedAnnotation::getAnnotation)
.map(annotationType::cast)
.orElse(null);
}
/**
* 当前合成注解中是否存在指定元注解
*
* @param annotationType 注解类型
* @return 是否
*/
@Override
public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
return synthesizedAnnotationMap.containsKey(annotationType);
}
/**
* 获取合成注解中包含的全部注解
*
* @return 注解对象
*/
@Override
public Annotation[] getAnnotations() {
return synthesizedAnnotationMap.values().stream()
.map(SynthesizedAnnotation::getAnnotation)
.toArray(Annotation[]::new);
}
/**
* 若合成注解在存在指定元注解,则使用动态代理生成一个对应的注解实例
*
* @param annotationType 注解类型
* @return 合成注解对象
* @see SynthesizedAnnotationProxy#create(Class, AnnotationAttributeValueProvider, SynthesizedAnnotation)
*/
@Override
public <T extends Annotation> T synthesize(Class<T> annotationType, SynthesizedAnnotation annotation) {
return SynthesizedAnnotationProxy.create(annotationType, this, annotation);
}
/**
* 注解包装类,表示{@link #source}以及{@link #source}所属层级结构中的全部关联注解对象
*
* @author huangchengxing
*/
public static class MetaAnnotation extends GenericSynthesizedAnnotation<Annotation, Annotation> {
/**
* 创建一个合成注解
*
* @param root 根对象
* @param annotation 被合成的注解对象
* @param verticalDistance 距离根对象的水平距离
* @param horizontalDistance 距离根对象的垂直距离
*/
protected MetaAnnotation(Annotation root, Annotation annotation, int verticalDistance, int horizontalDistance) {
super(root, annotation, verticalDistance, horizontalDistance);
}
}
}
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> 根对象类型
* @param <T> 注解类型
* @author huangchengxing
*/
public class GenericSynthesizedAnnotation<R, T extends Annotation> implements SynthesizedAnnotation {
private final R root;
private final T annotation;
private final Map<String, AnnotationAttribute> attributeMethodCaches;
private final int verticalDistance;
private final int horizontalDistance;
/**
* 创建一个合成注解
*
* @param root 根对象
* @param annotation 被合成的注解对象
* @param verticalDistance 距离根对象的水平距离
* @param horizontalDistance 距离根对象的垂直距离
*/
protected GenericSynthesizedAnnotation(
R root, T annotation, int verticalDistance, int horizontalDistance) {
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(ClassUtil.getDeclaredMethods(annotation.annotationType()))
.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 R getRoot() {
return root;
}
/**
* 获取被合成的注解对象
*
* @return 注解对象
*/
@Override
public T 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();
}
/**
* 获取注解属性值
*
* @param attributeName 属性名称
* @param attributeType 属性类型
* @return 注解属性值
*/
@Override
public Object getAttributeValue(String attributeName, Class<?> attributeType) {
return Opt.ofNullable(attributeMethodCaches.get(attributeName))
.filter(method -> ClassUtil.isAssignable(attributeType, method.getAttributeType()))
.map(AnnotationAttribute::getValue)
.get();
}
}
package cn.hutool.core.annotation;
import java.util.Comparator;
/**
* <p>描述以一个参照物为对象,存在于该参照物的层级结构中的对象。
*
* <p>该对象可通过{@link #getVerticalDistance()}与{@link #getHorizontalDistance()}
* 描述其在以参照物为基点的坐标坐标系中的位置。<br>
* 在需要对该接口的实现类进行按优先级排序时,距离{@link #getRoot()}对象越近,则该实现类的优先级越高。
* 默认提供了{@link #DEFAULT_HIERARCHICAL_COMPARATOR}用于实现该比较规则。<br>
* 一般情况下,{@link #getRoot()}返回值相同的对象之间的比较才有意义。
*
* <p>此外,还提供了{@link Selector}接口用于根据一定的规则从两个{@link Hierarchical}实现类中选择并返回一个最合适的对象,
* 默认提供了四个实现类:
* <ul>
* <li>{@link Selector#NEAREST_AND_OLDEST_PRIORITY}: 返回距离根对象更近的对象,当距离一样时优先返回旧对象;</li>
* <li>{@link Selector#NEAREST_AND_NEWEST_PRIORITY}: 返回距离根对象更近的对象,当距离一样时优先返回新对象;</li>
* <li>{@link Selector#FARTHEST_AND_OLDEST_PRIORITY}: 返回距离根对象更远的对象,当距离一样时优先返回旧对象;</li>
* <li>{@link Selector#FARTHEST_AND_NEWEST_PRIORITY}: 返回距离根对象更远的对象,当距离一样时优先返回新对象;</li>
* </ul>
*
* @author huangchengxing
*/
public interface Hierarchical extends Comparable<Hierarchical> {
// ====================== compare ======================
/**
* 默认{@link #getHorizontalDistance()}与{@link #getVerticalDistance()}排序的比较器
*/
Comparator<Hierarchical> DEFAULT_HIERARCHICAL_COMPARATOR = Comparator
.comparing(Hierarchical::getVerticalDistance)
.thenComparing(Hierarchical::getHorizontalDistance);
/**
* 按{@link #getVerticalDistance()}和{@link #getHorizontalDistance()}排序
*
* @param o {@link SynthesizedAnnotation}对象
* @return 比较值
*/
@Override
default int compareTo(Hierarchical o) {
return DEFAULT_HIERARCHICAL_COMPARATOR.compare(this, o);
}
// ====================== hierarchical ======================
/**
* 参照物,即坐标为{@code (0, 0)}的对象。
* 当对象本身即为参照物时,该方法应当返回其本身
*
* @return 参照物
*/
Object getRoot();
/**
* 获取该对象与参照物的垂直距离。
* 默认情况下,该距离即为当前对象与参照物之间相隔的层级数。
*
* @return 合成注解与根对象的垂直距离
*/
int getVerticalDistance();
/**
* 获取该对象与参照物的水平距离。
* 默认情况下,该距离即为当前对象在与参照物{@link #getVerticalDistance()}相同的情况下条,
* 该对象被扫描到的顺序。
*
* @return 合成注解与根对象的水平距离
*/
int getHorizontalDistance();
// ====================== selector ======================
/**
* {@link Hierarchical}选择器,用于根据一定的规则从两个{@link Hierarchical}实现类中选择并返回一个最合适的对象
*/
@FunctionalInterface
interface Selector {
/**
* 返回距离根对象更近的对象,当距离一样时优先返回旧对象
*/
Selector NEAREST_AND_OLDEST_PRIORITY = new NearestAndOldestPrioritySelector();
/**
* 返回距离根对象更近的对象,当距离一样时优先返回新对象
*/
Selector NEAREST_AND_NEWEST_PRIORITY = new NearestAndNewestPrioritySelector();
/**
* 返回距离根对象更远的对象,当距离一样时优先返回旧对象
*/
Selector FARTHEST_AND_OLDEST_PRIORITY = new FarthestAndOldestPrioritySelector();
/**
* 返回距离根对象更远的对象,当距离一样时优先返回新对象
*/
Selector FARTHEST_AND_NEWEST_PRIORITY = new FarthestAndNewestPrioritySelector();
/**
* 比较两个被合成的对象,选择其中的一个并返回
*
* @param <T> 复合注解类型
* @param prev 上一对象,该参数不允许为空
* @param next 下一对象,该参数不允许为空
* @return 对象
*/
<T extends Hierarchical> T choose(T prev, T next);
/**
* 返回距离根对象更近的注解,当距离一样时优先返回旧注解
*/
class NearestAndOldestPrioritySelector implements Selector {
@Override
public <T extends Hierarchical> T choose(T oldAnnotation, T newAnnotation) {
return newAnnotation.getVerticalDistance() < oldAnnotation.getVerticalDistance() ? newAnnotation : oldAnnotation;
}
}
/**
* 返回距离根对象更近的注解,当距离一样时优先返回新注解
*/
class NearestAndNewestPrioritySelector implements Selector {
@Override
public <T extends Hierarchical> T choose(T oldAnnotation, T newAnnotation) {
return newAnnotation.getVerticalDistance() <= oldAnnotation.getVerticalDistance() ? newAnnotation : oldAnnotation;
}
}
/**
* 返回距离根对象更远的注解,当距离一样时优先返回旧注解
*/
class FarthestAndOldestPrioritySelector implements Selector {
@Override
public <T extends Hierarchical> T choose(T oldAnnotation, T newAnnotation) {
return newAnnotation.getVerticalDistance() > oldAnnotation.getVerticalDistance() ? newAnnotation : oldAnnotation;
}
}
/**
* 返回距离根对象更远的注解,当距离一样时优先返回新注解
*/
class FarthestAndNewestPrioritySelector implements Selector {
@Override
public <T extends Hierarchical> T choose(T oldAnnotation, T newAnnotation) {
return newAnnotation.getVerticalDistance() >= oldAnnotation.getVerticalDistance() ? newAnnotation : oldAnnotation;
}
}
}
}
package cn.hutool.core.annotation;
import java.lang.annotation.*;
/**
* <p>用于在同一注解中,或具有一定关联的不同注解的属性中,表明这些属性之间具有特定的关联关系。
* 在通过{@link SynthesizedAggregateAnnotation}获取合成注解后,合成注解获取属性值时会根据该注解进行调整。<br>
*
* <p>该注解存在三个字注解:{@link MirrorFor}、{@link ForceAliasFor}或{@link AliasFor},
* 使用三个子注解等同于{@link Link}。但是需要注意的是,
* 当注解中的属性同时存在多个{@link Link}或基于{@link Link}的子注解时,
* 仅有声明在被注解的属性最上方的注解会生效,其余注解都将被忽略。
*
* <b>注意:该注解的优先级低于{@link Alias}</b>
*
* @author huangchengxing
* @see SynthesizedAggregateAnnotation
* @see RelationType
* @see AliasFor
* @see MirrorFor
* @see ForceAliasFor
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
public @interface Link {
/**
* 产生关联的注解类型,当不指定时,默认指注释的属性所在的类
*
* @return 关联的注解类型
*/
Class<? extends Annotation> annotation() default Annotation.class;
/**
* {@link #annotation()}指定注解中关联的属性
*
* @return 属性名
*/
String attribute() default "";
/**
* {@link #attribute()}指定属性与当前注解的属性建的关联关系类型
*
* @return 关系类型
*/
RelationType type() default RelationType.MIRROR_FOR;
}
package cn.hutool.core.annotation;
import java.lang.annotation.*;
/**
* <p>{@link Link}的子注解。表示注解的属性与指定的属性互为镜像,通过一个属性将能够获得对方的值。<br>
* 它们遵循下述规则:
* <ul>
* <li>互为镜像的两个属性,必须同时通过指定模式为{@code MIRROR_FOR}的{@link Link}注解指定对方;</li>
* <li>互为镜像的两个属性,类型必须一致;</li>
* <li>互为镜像的两个属性在获取值,且两者的值皆不同时,必须且仅允许有一个非默认值,该值被优先返回;</li>
* <li>互为镜像的两个属性,在值都为默认值或都不为默认值时,两者的值必须相等;</li>
* </ul>
* <b>注意,该注解与{@link Link}、{@link ForceAliasFor}或{@link AliasFor}一起使用时,将只有被声明在最上面的注解会生效</b>
*
* @author huangchengxing
* @see Link
* @see RelationType#MIRROR_FOR
*/
@Link(type = RelationType.MIRROR_FOR)
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
public @interface MirrorFor {
/**
* 产生关联的注解类型,当不指定时,默认指注释的属性所在的类
*
* @return 关联的注解类型
*/
@Link(annotation = Link.class, attribute = "annotation", type = RelationType.FORCE_ALIAS_FOR)
Class<? extends Annotation> annotation() default Annotation.class;
/**
* {@link #annotation()}指定注解中关联的属性
*
* @return 属性名
*/
@Link(annotation = Link.class, attribute = "attribute", type = RelationType.FORCE_ALIAS_FOR)
String attribute() default "";
}
package cn.hutool.core.annotation;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.text.CharSequenceUtil;
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 synthesizer 注解合成器
* @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(
AnnotationSynthesizer synthesizer, Link annotation,
SynthesizedAnnotation originalAnnotation, AnnotationAttribute originalAttribute,
SynthesizedAnnotation linkedAnnotation, AnnotationAttribute linkedAttribute) {
// 镜像属性必然成对出现,因此此处必定存在三种情况:
// 1.两属性都不为镜像属性,此时继续进行后续处理;
// 2.两属性都为镜像属性,并且指向对方,此时无需后续处理;
// 3.两属性仅有任意一属性为镜像属性,此时镜像属性必然未指向当前原始属性,此时应该抛出异常;
if (originalAttribute instanceof MirroredAnnotationAttribute
|| linkedAttribute instanceof MirroredAnnotationAttribute) {
checkMirrored(originalAttribute, linkedAttribute);
return;
}
// 校验镜像关系
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 checkMirrored(AnnotationAttribute original, AnnotationAttribute mirror) {
final boolean originalAttributeMirrored = original instanceof MirroredAnnotationAttribute;
final boolean mirrorAttributeMirrored = mirror instanceof MirroredAnnotationAttribute;
// 校验通过
final boolean passed = originalAttributeMirrored && mirrorAttributeMirrored
&& ObjectUtil.equals(((MirroredAnnotationAttribute)original).getLinked(), ((MirroredAnnotationAttribute)mirror).getOriginal());
if (passed) {
return;
}
// 校验失败,拼装异常信息用于抛出异常
String errorMsg;
// 原始字段已经跟其他字段形成镜像
if (originalAttributeMirrored && !mirrorAttributeMirrored) {
errorMsg = CharSequenceUtil.format(
"attribute [{}] cannot mirror for [{}], because it's already mirrored for [{}]",
original.getAttribute(), mirror.getAttribute(), ((MirroredAnnotationAttribute)original).getLinked()
);
}
// 镜像字段已经跟其他字段形成镜像
else if (!originalAttributeMirrored && mirrorAttributeMirrored) {
errorMsg = CharSequenceUtil.format(
"attribute [{}] cannot mirror for [{}], because it's already mirrored for [{}]",
mirror.getAttribute(), original.getAttribute(), ((MirroredAnnotationAttribute)mirror).getLinked()
);
}
// 两者都形成了镜像,但是都未指向对方,理论上不会存在该情况
else {
errorMsg = CharSequenceUtil.format(
"attribute [{}] cannot mirror for [{}], because [{}] already mirrored for [{}] and [{}] already mirrored for [{}]",
mirror.getAttribute(), original.getAttribute(),
mirror.getAttribute(), ((MirroredAnnotationAttribute)mirror).getLinked(),
original.getAttribute(), ((MirroredAnnotationAttribute)original).getLinked()
);
}
throw new IllegalArgumentException(errorMsg);
}
/**
* 基本校验
*/
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);
}
}
package cn.hutool.core.annotation;
import cn.hutool.core.lang.Assert;
/**
* 表示存在对应镜像属性的注解属性,当获取值时将根据{@link RelationType#MIRROR_FOR}的规则进行处理
*
* @author huangchengxing
* @see MirrorLinkAnnotationPostProcessor
* @see RelationType#MIRROR_FOR
*/
public class MirroredAnnotationAttribute extends AbstractWrappedAnnotationAttribute {
public MirroredAnnotationAttribute(AnnotationAttribute origin, AnnotationAttribute linked) {
super(origin, linked);
}
@Override
public Object getValue() {
final boolean originIsDefault = original.isValueEquivalentToDefaultValue();
final boolean targetIsDefault = linked.isValueEquivalentToDefaultValue();
final Object originValue = original.getValue();
final Object targetValue = linked.getValue();
// 都为默认值,或都为非默认值时,两方法的返回值必须相等
if (originIsDefault == targetIsDefault) {
Assert.equals(
originValue, targetValue,
"the values of attributes [{}] and [{}] that mirror each other are different: [{}] <==> [{}]",
original.getAttribute(), linked.getAttribute(), originValue, targetValue
);
return originValue;
}
// 两者有一者不为默认值时,优先返回非默认值
return originIsDefault ? targetValue : originValue;
}
/**
* 当{@link #original}与{@link #linked}都为默认值时返回{@code true}
*
* @return 是否
*/
@Override
public boolean isValueEquivalentToDefaultValue() {
return original.isValueEquivalentToDefaultValue() && linked.isValueEquivalentToDefaultValue();
}
}
package cn.hutool.core.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 属性忽略注解,使用此注解的字段等会被忽略,主要用于Bean拷贝、Bean转Map等<br>
* 此注解应用于字段时,忽略读取和设置属性值,应用于setXXX方法忽略设置值,应用于getXXX忽略读取值
*
* @author Looly
* @since 5.4.2
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
public @interface PropIgnore {
}
package cn.hutool.core.annotation;
/**
* <p>注解属性的关系类型 <br>
* 若将被{@link Link}注解的属性称为“原始属性”,而在{@link Link}注解中指向的注解属性称为“关联属性”,
* 则该枚举用于描述“原始属性”与“关联属性”在{@link SynthesizedAggregateAnnotation}处理过程中的作用关系。<br>
* 根据在{@link Link#type()}中指定的关系类型的不同,通过{@link SynthesizedAggregateAnnotation}合成的注解的属性值也将有所变化。
*
* <p>当一个注解中的所有属性同时具备多种关系时,将依次按下述顺序处理:
* <ol>
* <li>属性上的{@link Alias}注解;</li>
* <li>属性上的{@link Link}注解,且{@link Link#type()}为{@link #MIRROR_FOR};</li>
* <li>属性上的{@link Link}注解,且{@link Link#type()}为{@link #FORCE_ALIAS_FOR};</li>
* <li>属性上的{@link Link}注解,且{@link Link#type()}为{@link #ALIAS_FOR};</li>
* </ol>
*
* @author huangchengxing
* @see SynthesizedAggregateAnnotation
* @see Link
*/
public enum RelationType {
/**
* <p>表示注解的属性与指定的属性互为镜像,通过一个属性将能够获得对方的值。<br>
* 它们遵循下述规则:
* <ul>
* <li>互为镜像的两个属性,必须同时通过指定模式为{@code MIRROR_FOR}的{@link Link}注解指定对方;</li>
* <li>互为镜像的两个属性,类型必须一致;</li>
* <li>互为镜像的两个属性在获取值,且两者的值皆不同时,必须且仅允许有一个非默认值,该值被优先返回;</li>
* <li>互为镜像的两个属性,在值都为默认值或都不为默认值时,两者的值必须相等;</li>
* </ul>
*/
MIRROR_FOR,
/**
* <p>表示“原始属性”将作为“关联属性”的别名。
* <ul>
* <li>当“原始属性”为默认值时,获取“关联属性”将返回“关联属性”本身的值;</li>
* <li>当“原始属性”不为默认值时,获取“关联属性”将返回“原始属性”的值;</li>
* </ul>
*/
ALIAS_FOR,
/**
* <p>表示“原始属性”将强制作为“关联属性”的别名。效果等同于在“原始属性”上添加{@link Alias}注解,
* 任何情况下,获取“关联属性”的值都将直接返回“原始属性”的值
*/
FORCE_ALIAS_FOR;
}
package cn.hutool.core.annotation;
import java.lang.annotation.Annotation;
/**
* <p>表示基于特定规则聚合,将一组注解聚合而来的注解对象,
* 该注解对象允许根据一定规则“合成”一些跟原始注解属性不一样合成注解。
*
* <p>合成注解一般被用于处理类层级结果中具有直接或间接关联的注解对象,
* 当实例被创建时,会获取到这些注解对象,并使用{@link SynthesizedAnnotationSelector}对类型相同的注解进行过滤,
* 并最终得到类型不重复的有效注解对象。这些有效注解将被包装为{@link SynthesizedAnnotation},
* 然后最终用于“合成”一个{@link SynthesizedAggregateAnnotation}。<br>
* {@link SynthesizedAnnotationSelector}是合成注解生命周期中的第一个钩子,
* 自定义选择器以拦截原始注解被扫描的过程。
*
* <p>当合成注解完成对待合成注解的扫描,并完成了必要属性的加载后,
* 将会按顺序依次调用{@link SynthesizedAnnotationPostProcessor},
* 注解后置处理器允许用于对完成注解的待合成注解进行二次调整,
* 该钩子一般用于根据{@link Link}注解对属性进行调整。<br>
* {@link SynthesizedAnnotationPostProcessor}是合成注解生命周期中的第二个钩子,
* 自定义后置处理器以拦截原始在转为待合成注解后的初始化过程。
*
* <p>合成注解允许通过{@link #synthesize(Class)}合成一个指定的注解对象,
* 该方法返回的注解对象可能是原始的注解对象,也有可能通过动态代理的方式生成,
* 该对象实例的属性不一定来自对象本身,而是来自于经过{@link SynthesizedAnnotationAttributeProcessor}
* 处理后的、用于合成当前实例的全部关联注解的相关属性。<br>
* {@link SynthesizedAnnotationAttributeProcessor}是合成注解生命周期中的第三个钩子,
* 自定义属性处理器以拦截合成注解的取值过程。
*
* @author huangchengxing
* @see AnnotationSynthesizer
* @see SynthesizedAnnotation
* @see SynthesizedAnnotationSelector
* @see SynthesizedAnnotationAttributeProcessor
* @see SynthesizedAnnotationPostProcessor
* @see GenericSynthesizedAggregateAnnotation
*/
public interface SynthesizedAggregateAnnotation extends AggregateAnnotation, Hierarchical, AnnotationSynthesizer, AnnotationAttributeValueProvider {
// ================== hierarchical ==================
/**
* 距离{@link #getRoot()}返回值的垂直距离,
* 默认聚合注解即为根对象,因此返回0
*
* @return 距离{@link #getRoot()}返回值的水平距离,
*/
@Override
default int getVerticalDistance() {
return 0;
}
/**
* 距离{@link #getRoot()}返回值的水平距离,
* 默认聚合注解即为根对象,因此返回0
*
* @return 距离{@link #getRoot()}返回值的水平距离,
*/
@Override
default int getHorizontalDistance() {
return 0;
}
// ================== synthesize ==================
/**
* 获取在聚合中存在的指定注解对象
*
* @param annotationType 注解类型
* @param <T> 注解类型
* @return 注解对象
*/
<T extends Annotation> T getAnnotation(Class<T> annotationType);
/**
* 获取合成注解属性处理器
*
* @return 合成注解属性处理器
*/
SynthesizedAnnotationAttributeProcessor getAnnotationAttributeProcessor();
/**
* 获取当前的注解类型
*
* @return 注解类型
*/
@Override
default Class<? extends Annotation> annotationType() {
return this.getClass();
}
/**
* 从聚合中获取指定类型的属性值
*
* @param attributeName 属性名称
* @param attributeType 属性类型
* @return 属性值
*/
@Override
Object getAttributeValue(String attributeName, Class<?> attributeType);
}
package cn.hutool.core.annotation;
import cn.hutool.core.collection.CollUtil;
import java.lang.annotation.Annotation;
import java.util.Map;
import java.util.function.UnaryOperator;
/**
* <p>用于在{@link SynthesizedAggregateAnnotation}中表示一个处于合成状态的注解对象。<br>
* 当对多个合成注解排序时,默认使用{@link #DEFAULT_HIERARCHICAL_COMPARATOR}进行排序,
* 从保证合成注解按{@link #getVerticalDistance()}与{@link #getHorizontalDistance()}的返回值保持有序,
* 从而使得距离根元素更接近的注解对象在被处理是具有更高的优先级。
*
* @author huangchengxing
* @see SynthesizedAggregateAnnotation
*/
public interface SynthesizedAnnotation extends Annotation, Hierarchical, AnnotationAttributeValueProvider {
/**
* 获取被合成的注解对象
*
* @return 注解对象
*/
Annotation getAnnotation();
/**
* 获取该合成注解与根对象的垂直距离。
* 默认情况下,该距离即为当前注解与根对象之间相隔的层级数。
*
* @return 合成注解与根对象的垂直距离
*/
@Override
int getVerticalDistance();
/**
* 获取该合成注解与根对象的水平距离。
* 默认情况下,该距离即为当前注解与根对象之间相隔的已经被扫描到的注解数。
*
* @return 合成注解与根对象的水平距离
*/
@Override
int getHorizontalDistance();
/**
* 注解是否存在该名称相同,且类型一致的属性
*
* @param attributeName 属性名
* @param returnType 返回值类型
* @return 是否存在该属性
*/
boolean hasAttribute(String attributeName, Class<?> returnType);
/**
* 获取该注解的全部属性
*
* @return 注解属性
*/
Map<String, AnnotationAttribute> getAttributes();
/**
* 设置该注解的全部属性
*
* @param attributes 注解属性
*/
default void setAttributes(Map<String, AnnotationAttribute> attributes) {
if (CollUtil.isNotEmpty(attributes)) {
attributes.forEach(this::setAttribute);
}
}
/**
* 设置属性值
*
* @param attributeName 属性名称
* @param attribute 注解属性
*/
void setAttribute(String attributeName, AnnotationAttribute attribute);
/**
* 替换属性值
*
* @param attributeName 属性名
* @param operator 替换操作
*/
void replaceAttribute(String attributeName, UnaryOperator<AnnotationAttribute> operator);
/**
* 获取属性值
*
* @param attributeName 属性名
* @return 属性值
*/
Object getAttributeValue(String attributeName);
}
package cn.hutool.core.annotation;
import java.util.Collection;
/**
* 合成注解属性选择器。用于在{@link SynthesizedAggregateAnnotation}中从指定类型的合成注解里获取到对应的属性值
*
* @author huangchengxing
*/
@FunctionalInterface
public interface SynthesizedAnnotationAttributeProcessor {
/**
* 从一批被合成注解中,获取指定名称与类型的属性值
*
* @param attributeName 属性名称
* @param attributeType 属性类型
* @param synthesizedAnnotations 被合成的注解
* @param <R> 属性类型
* @return 属性值
*/
<R> R getAttributeValue(String attributeName, Class<R> attributeType, Collection<? extends SynthesizedAnnotation> synthesizedAnnotations);
}
package cn.hutool.core.annotation;
import cn.hutool.core.comparator.CompareUtil;
import java.util.Comparator;
/**
* <p>被合成注解后置处理器,用于在{@link SynthesizedAggregateAnnotation}加载完所有待合成注解后,
* 再对加载好的{@link SynthesizedAnnotation}进行后置处理。<br>
* 当多个{@link SynthesizedAnnotationPostProcessor}需要一起执行时,将按照{@link #order()}的返回值进行排序,
* 该值更小的处理器将被优先执行。
*
* <p>该接口存在多个实现类,调用者应当保证在任何时候,对一批后置处理器的调用顺序都符合:
* <ul>
* <li>{@link AliasAnnotationPostProcessor};</li>
* <li>{@link MirrorLinkAnnotationPostProcessor};</li>
* <li>{@link AliasLinkAnnotationPostProcessor};</li>
* <li>其他后置处理器;</li>
* </ul>
*
* @author huangchengxing
* @see AliasAnnotationPostProcessor
* @see MirrorLinkAnnotationPostProcessor
* @see AliasLinkAnnotationPostProcessor
*/
public interface SynthesizedAnnotationPostProcessor extends Comparable<SynthesizedAnnotationPostProcessor> {
/**
* 属性上带有{@link Alias}的注解对象的后置处理器
*/
AliasAnnotationPostProcessor ALIAS_ANNOTATION_POST_PROCESSOR = new AliasAnnotationPostProcessor();
/**
* 属性上带有{@link Link},且与其他注解的属性存在镜像关系的注解对象的后置处理器
*/
MirrorLinkAnnotationPostProcessor MIRROR_LINK_ANNOTATION_POST_PROCESSOR = new MirrorLinkAnnotationPostProcessor();
/**
* 属性上带有{@link Link},且与其他注解的属性存在别名关系的注解对象的后置处理器
*/
AliasLinkAnnotationPostProcessor ALIAS_LINK_ANNOTATION_POST_PROCESSOR = new AliasLinkAnnotationPostProcessor();
/**
* 在一组后置处理器中被调用的顺序,越小越靠前
*
* @return 排序值
*/
default int order() {
return Integer.MAX_VALUE;
}
/**
* 比较两个后置处理器的{@link #order()}返回值
*
* @param o 比较对象
* @return 大小
*/
@Override
default int compareTo(SynthesizedAnnotationPostProcessor o) {
return CompareUtil.compare(this, o, Comparator.comparing(SynthesizedAnnotationPostProcessor::order));
}
/**
* 给定指定被合成注解与其所属的合成注解聚合器实例,经过处理后返回最终
*
* @param synthesizedAnnotation 合成的注解
* @param synthesizer 注解合成器
*/
void process(SynthesizedAnnotation synthesizedAnnotation, AnnotationSynthesizer synthesizer);
}
package cn.hutool.core.annotation;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* 合成注解代理类,用于为{@link SynthesizedAnnotation}生成对应的合成注解代理对象
*
* @author huangchengxing
* @see SynthesizedAnnotation
* @see AnnotationAttributeValueProvider
*/
public class SynthesizedAnnotationProxy implements InvocationHandler {
private final AnnotationAttributeValueProvider annotationAttributeValueProvider;
private final SynthesizedAnnotation annotation;
private final Map<String, BiFunction<Method, Object[], Object>> methods;
/**
* 创建一个代理注解,生成的代理对象将是{@link SyntheticProxyAnnotation}与指定的注解类的子类。
*
* @param <T> 注解类型
* @param annotationType 注解类型
* @param annotationAttributeValueProvider 注解属性值获取器
* @param annotation 合成注解
* @return 代理注解
*/
@SuppressWarnings("unchecked")
public static <T extends Annotation> T create(
Class<T> annotationType,
AnnotationAttributeValueProvider annotationAttributeValueProvider,
SynthesizedAnnotation annotation) {
if (ObjectUtil.isNull(annotation)) {
return null;
}
final SynthesizedAnnotationProxy proxyHandler = new SynthesizedAnnotationProxy(annotationAttributeValueProvider, annotation);
if (ObjectUtil.isNull(annotation)) {
return null;
}
return (T) Proxy.newProxyInstance(
annotationType.getClassLoader(),
new Class[]{annotationType, SyntheticProxyAnnotation.class},
proxyHandler
);
}
/**
* 创建一个代理注解,生成的代理对象将是{@link SyntheticProxyAnnotation}与指定的注解类的子类。
*
* @param <T> 注解类型
* @param annotationType 注解类型
* @param annotation 合成注解
* @return 代理注解
*/
public static <T extends Annotation> T create(
Class<T> annotationType, SynthesizedAnnotation annotation) {
return create(annotationType, annotation, annotation);
}
/**
* 该类是否为通过{@code SynthesizedAnnotationProxy}生成的代理类
*
* @param annotationType 注解类型
* @return 是否
*/
public static boolean isProxyAnnotation(Class<?> annotationType) {
return ClassUtil.isAssignable(SyntheticProxyAnnotation.class, annotationType);
}
SynthesizedAnnotationProxy(AnnotationAttributeValueProvider annotationAttributeValueProvider, SynthesizedAnnotation annotation) {
Assert.notNull(annotationAttributeValueProvider, "annotationAttributeValueProvider must not null");
Assert.notNull(annotation, "annotation must not null");
this.annotationAttributeValueProvider = annotationAttributeValueProvider;
this.annotation = annotation;
this.methods = new HashMap<>(9);
loadMethods();
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return Opt.ofNullable(methods.get(method.getName()))
.map(m -> m.apply(method, args))
.orElseGet(() -> ReflectUtil.invoke(this, method, args));
}
// ========================= 代理方法 =========================
void loadMethods() {
methods.put("toString", (method, args) -> proxyToString());
methods.put("hashCode", (method, args) -> proxyHashCode());
methods.put("getSynthesizedAnnotation", (method, args) -> proxyGetSynthesizedAnnotation());
methods.put("getRoot", (method, args) -> annotation.getRoot());
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]));
methods.put("getAttributes", (method, args) -> annotation.getAttributes());
methods.put("setAttribute", (method, args) -> {
throw new UnsupportedOperationException("proxied annotation can not reset attributes");
});
methods.put("getAttributeValue", (method, args) -> annotation.getAttributeValue((String) args[0]));
methods.put("annotationType", (method, args) -> annotation.annotationType());
for (final Method declaredMethod : ClassUtil.getDeclaredMethods(annotation.getAnnotation().annotationType())) {
methods.put(declaredMethod.getName(), (method, args) -> proxyAttributeValue(method));
}
}
private String proxyToString() {
final String attributes = Stream.of(ClassUtil.getDeclaredMethods(annotation.getAnnotation().annotationType()))
.filter(AnnotationUtil::isAttributeMethod)
.map(method -> CharSequenceUtil.format(
"{}={}", method.getName(), proxyAttributeValue(method))
)
.collect(Collectors.joining(", "));
return CharSequenceUtil.format("@{}({})", annotation.annotationType().getName(), attributes);
}
private int proxyHashCode() {
return Objects.hash(annotationAttributeValueProvider, annotation);
}
private Object proxyGetSynthesizedAnnotation() {
return annotation;
}
private Object proxyAttributeValue(Method attributeMethod) {
return annotationAttributeValueProvider.getAttributeValue(attributeMethod.getName(), attributeMethod.getReturnType());
}
/**
* 通过代理类生成的合成注解
*
* @author huangchengxing
*/
interface SyntheticProxyAnnotation extends SynthesizedAnnotation {
/**
* 获取该代理注解对应的已合成注解
*
* @return 理注解对应的已合成注解
*/
SynthesizedAnnotation getSynthesizedAnnotation();
}
}
package cn.hutool.core.annotation;
/**
* 注解选择器,指定两个注解,选择其中一个返回。<br>
* 该接口用于在{@link SynthesizedAggregateAnnotation}中用于从一批相同的注解对象中筛选最终用于合成注解对象。
*
* @author huangchengxing
*/
@FunctionalInterface
public interface SynthesizedAnnotationSelector {
/**
* 返回距离根对象更近的注解,当距离一样时优先返回旧注解
*/
SynthesizedAnnotationSelector NEAREST_AND_OLDEST_PRIORITY = new NearestAndOldestPrioritySelector();
/**
* 返回距离根对象更近的注解,当距离一样时优先返回新注解
*/
SynthesizedAnnotationSelector NEAREST_AND_NEWEST_PRIORITY = new NearestAndNewestPrioritySelector();
/**
* 返回距离根对象更远的注解,当距离一样时优先返回旧注解
*/
SynthesizedAnnotationSelector FARTHEST_AND_OLDEST_PRIORITY = new FarthestAndOldestPrioritySelector();
/**
* 返回距离根对象更远的注解,当距离一样时优先返回新注解
*/
SynthesizedAnnotationSelector FARTHEST_AND_NEWEST_PRIORITY = new FarthestAndNewestPrioritySelector();
/**
* 比较两个被合成的注解,选择其中的一个并返回
*
* @param <T> 复合注解类型
* @param oldAnnotation 已存在的注解,该参数不允许为空
* @param newAnnotation 新获取的注解,该参数不允许为空
* @return 被合成的注解
*/
<T extends SynthesizedAnnotation> T choose(T oldAnnotation, T newAnnotation);
/**
* 返回距离根对象更近的注解,当距离一样时优先返回旧注解
*/
class NearestAndOldestPrioritySelector implements SynthesizedAnnotationSelector {
@Override
public <T extends SynthesizedAnnotation> T choose(T oldAnnotation, T newAnnotation) {
return Hierarchical.Selector.NEAREST_AND_OLDEST_PRIORITY.choose(oldAnnotation, newAnnotation);
}
}
/**
* 返回距离根对象更近的注解,当距离一样时优先返回新注解
*/
class NearestAndNewestPrioritySelector implements SynthesizedAnnotationSelector {
@Override
public <T extends SynthesizedAnnotation> T choose(T oldAnnotation, T newAnnotation) {
return Hierarchical.Selector.NEAREST_AND_NEWEST_PRIORITY.choose(oldAnnotation, newAnnotation);
}
}
/**
* 返回距离根对象更远的注解,当距离一样时优先返回旧注解
*/
class FarthestAndOldestPrioritySelector implements SynthesizedAnnotationSelector {
@Override
public <T extends SynthesizedAnnotation> T choose(T oldAnnotation, T newAnnotation) {
return Hierarchical.Selector.FARTHEST_AND_OLDEST_PRIORITY.choose(oldAnnotation, newAnnotation);
}
}
/**
* 返回距离根对象更远的注解,当距离一样时优先返回新注解
*/
class FarthestAndNewestPrioritySelector implements SynthesizedAnnotationSelector {
@Override
public <T extends SynthesizedAnnotation> T choose(T oldAnnotation, T newAnnotation) {
return Hierarchical.Selector.FARTHEST_AND_NEWEST_PRIORITY.choose(oldAnnotation, newAnnotation);
}
}
}
package cn.hutool.core.annotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Collection;
/**
* <p>表示一个被包装过的{@link AnnotationAttribute},
* 该实例中的一些方法可能会被代理到另一个注解属性对象中,
* 从而使得通过原始的注解属性的方法获取到另一注解属性的值。<br>
* 除了{@link #getValue()}以外,其他方法的返回值应当尽可能与{@link #getOriginal()}
* 返回的{@link AnnotationAttribute}对象的方法返回值一致。
*
* <p>当包装类被包装了多层后,则规则生效优先级按包装的先后顺序倒序排序,
* 比如a、b互为镜像,此时a、b两属性应当都被{@link MirroredAnnotationAttribute}包装,
* 若再指定c为a的别名字段,则c、a、b都要在原基础上再次包装一层{@link AliasedAnnotationAttribute}。<br>
* 此时a、b同时被包装了两层,则执行时,优先执行{@link AliasedAnnotationAttribute}的逻辑,
* 当该规则不生效时,比如c只有默认值,此时上一次的{@link MirroredAnnotationAttribute}的逻辑才会生效。
*
* <p>被包装的{@link AnnotationAttribute}实际结构为一颗二叉树,
* 当包装类再次被包装时,实际上等于又添加了一个新的根节点,
* 此时需要同时更新树的全部关联叶子节点。
*
* @author huangchengxing
* @see AnnotationAttribute
* @see ForceAliasedAnnotationAttribute
* @see AliasedAnnotationAttribute
* @see MirroredAnnotationAttribute
*/
public interface WrappedAnnotationAttribute extends AnnotationAttribute {
// =========================== 新增方法 ===========================
/**
* 获取被包装的{@link AnnotationAttribute}对象,该对象也可能是{@link AnnotationAttribute}
*
* @return 被包装的{@link AnnotationAttribute}对象
*/
AnnotationAttribute getOriginal();
/**
* 获取最初的被包装的{@link AnnotationAttribute}
*
* @return 最初的被包装的{@link AnnotationAttribute}
*/
AnnotationAttribute getNonWrappedOriginal();
/**
* 获取包装{@link #getOriginal()}的{@link AnnotationAttribute}对象,该对象也可能是{@link AnnotationAttribute}
*
* @return 包装对象
*/
AnnotationAttribute getLinked();
/**
* 遍历以当前实例为根节点的树结构,获取所有未被包装的属性
*
* @return 叶子节点
*/
Collection<AnnotationAttribute> getAllLinkedNonWrappedAttributes();
// =========================== 代理实现 ===========================
/**
* 获取注解对象
*
* @return 注解对象
*/
@Override
default Annotation getAnnotation() {
return getOriginal().getAnnotation();
}
/**
* 获取注解属性对应的方法
*
* @return 注解属性对应的方法
*/
@Override
default Method getAttribute() {
return getOriginal().getAttribute();
}
/**
* 该注解属性的值是否等于默认值 <br>
* 默认仅当{@link #getOriginal()}与{@link #getLinked()}返回的注解属性
* 都为默认值时,才返回{@code true}
*
* @return 该注解属性的值是否等于默认值
*/
@Override
boolean isValueEquivalentToDefaultValue();
/**
* 获取属性类型
*
* @return 属性类型
*/
@Override
default Class<?> getAttributeType() {
return getOriginal().getAttributeType();
}
/**
* 获取属性上的注解
*
* @param annotationType 注解类型
* @return 注解对象
*/
@Override
default <T extends Annotation> T getAnnotation(Class<T> annotationType) {
return getOriginal().getAnnotation(annotationType);
}
/**
* 当前注解属性是否已经被{@link WrappedAnnotationAttribute}包装
*
* @return boolean
*/
@Override
default boolean isWrapped() {
return true;
}
}
/**
* 注解包,提供增强型注解和注解工具类
*
* @author looly
*
*/
package cn.hutool.core.annotation;
\ No newline at end of file
package cn.hutool.core.annotation.scanner;
import cn.hutool.core.annotation.AnnotationUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Proxy;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
/**
* 为需要从类的层级结构中获取注解的{@link AnnotationScanner}提供基本实现
*
* @author huangchengxing
*/
public abstract class AbstractTypeAnnotationScanner<T extends AbstractTypeAnnotationScanner<T>> implements AnnotationScanner {
/**
* 是否允许扫描父类
*/
private boolean includeSuperClass;
/**
* 是否允许扫描父接口
*/
private boolean includeInterfaces;
/**
* 过滤器,若类型无法通过该过滤器,则该类型及其树结构将直接不被查找
*/
private Predicate<Class<?>> filter;
/**
* 排除的类型,以上类型及其树结构将直接不被查找
*/
private final Set<Class<?>> excludeTypes;
/**
* 转换器
*/
private final List<UnaryOperator<Class<?>>> converters;
/**
* 是否有转换器
*/
private boolean hasConverters;
/**
* 当前实例
*/
private final T typedThis;
/**
* 构造一个类注解扫描器
*
* @param includeSuperClass 是否允许扫描父类
* @param includeInterfaces 是否允许扫描父接口
* @param filter 过滤器
* @param excludeTypes 不包含的类型
*/
@SuppressWarnings("unchecked")
protected AbstractTypeAnnotationScanner(boolean includeSuperClass, boolean includeInterfaces, Predicate<Class<?>> filter, Set<Class<?>> excludeTypes) {
Assert.notNull(filter, "filter must not null");
Assert.notNull(excludeTypes, "excludeTypes must not null");
this.includeSuperClass = includeSuperClass;
this.includeInterfaces = includeInterfaces;
this.filter = filter;
this.excludeTypes = excludeTypes;
this.converters = new ArrayList<>();
this.typedThis = (T) this;
}
/**
* 是否允许扫描父类
*
* @return 是否允许扫描父类
*/
public boolean isIncludeSuperClass() {
return includeSuperClass;
}
/**
* 是否允许扫描父接口
*
* @return 是否允许扫描父接口
*/
public boolean isIncludeInterfaces() {
return includeInterfaces;
}
/**
* 设置过滤器,若类型无法通过该过滤器,则该类型及其树结构将直接不被查找
*
* @param filter 过滤器
* @return 当前实例
*/
public T setFilter(Predicate<Class<?>> filter) {
Assert.notNull(filter, "filter must not null");
this.filter = filter;
return typedThis;
}
/**
* 添加不扫描的类型,该类型及其树结构将直接不被查找
*
* @param excludeTypes 不扫描的类型
* @return 当前实例
*/
public T addExcludeTypes(Class<?>... excludeTypes) {
CollUtil.addAll(this.excludeTypes, excludeTypes);
return typedThis;
}
/**
* 添加转换器
*
* @param converter 转换器
* @return 当前实例
* @see JdkProxyClassConverter
*/
public T addConverters(UnaryOperator<Class<?>> converter) {
Assert.notNull(converter, "converter must not null");
this.converters.add(converter);
if (!this.hasConverters) {
this.hasConverters = CollUtil.isNotEmpty(this.converters);
}
return typedThis;
}
/**
* 是否允许扫描父类
*
* @param includeSuperClass 是否
* @return 当前实例
*/
protected T setIncludeSuperClass(boolean includeSuperClass) {
this.includeSuperClass = includeSuperClass;
return typedThis;
}
/**
* 是否允许扫描父接口
*
* @param includeInterfaces 是否
* @return 当前实例
*/
protected T setIncludeInterfaces(boolean includeInterfaces) {
this.includeInterfaces = includeInterfaces;
return typedThis;
}
/**
* 则根据广度优先递归扫描类的层级结构,并对层级结构中类/接口声明的层级索引和它们声明的注解对象进行处理
*
* @param consumer 对获取到的注解和注解对应的层级索引的处理
* @param annotatedEle 注解元素
* @param filter 注解过滤器,无法通过过滤器的注解不会被处理。该参数允许为空。
*/
@Override
public void scan(BiConsumer<Integer, Annotation> consumer, AnnotatedElement annotatedEle, Predicate<Annotation> filter) {
filter = ObjectUtil.defaultIfNull(filter, a -> annotation -> true);
final Class<?> sourceClass = getClassFormAnnotatedElement(annotatedEle);
final Deque<List<Class<?>>> classDeque = CollUtil.newLinkedList(CollUtil.newArrayList(sourceClass));
final Set<Class<?>> accessedTypes = new LinkedHashSet<>();
int index = 0;
while (!classDeque.isEmpty()) {
final List<Class<?>> currClassQueue = classDeque.removeFirst();
final List<Class<?>> nextClassQueue = new ArrayList<>();
for (Class<?> targetClass : currClassQueue) {
targetClass = convert(targetClass);
// 过滤不需要处理的类
if (isNotNeedProcess(accessedTypes, targetClass)) {
continue;
}
accessedTypes.add(targetClass);
// 扫描父类
scanSuperClassIfNecessary(nextClassQueue, targetClass);
// 扫描接口
scanInterfaceIfNecessary(nextClassQueue, targetClass);
// 处理层级索引和注解
final Annotation[] targetAnnotations = getAnnotationsFromTargetClass(annotatedEle, index, targetClass);
for (final Annotation annotation : targetAnnotations) {
if (AnnotationUtil.isNotJdkMateAnnotation(annotation.annotationType()) && filter.test(annotation)) {
consumer.accept(index, annotation);
}
}
index++;
}
if (CollUtil.isNotEmpty(nextClassQueue)) {
classDeque.addLast(nextClassQueue);
}
}
}
/**
* 从要搜索的注解元素上获得要递归的类型
*
* @param annotatedElement 注解元素
* @return 要递归的类型
*/
protected abstract Class<?> getClassFormAnnotatedElement(AnnotatedElement annotatedElement);
/**
* 从类上获取最终所需的目标注解
*
* @param source 最初的注解元素
* @param index 类的层级索引
* @param targetClass 类
* @return 最终所需的目标注解
*/
protected abstract Annotation[] getAnnotationsFromTargetClass(AnnotatedElement source, int index, Class<?> targetClass);
/**
* 当前类是否不需要处理
*
* @param accessedTypes 访问类型
* @param targetClass 目标类型
* @return 是否不需要处理
*/
protected boolean isNotNeedProcess(Set<Class<?>> accessedTypes, Class<?> targetClass) {
return ObjectUtil.isNull(targetClass)
|| accessedTypes.contains(targetClass)
|| excludeTypes.contains(targetClass)
|| filter.negate().test(targetClass);
}
/**
* 若{@link #includeInterfaces}为{@code true},则将目标类的父接口也添加到nextClasses
*
* @param nextClasses 下一个类集合
* @param targetClass 目标类型
*/
protected void scanInterfaceIfNecessary(List<Class<?>> nextClasses, Class<?> targetClass) {
if (includeInterfaces) {
final Class<?>[] interfaces = targetClass.getInterfaces();
if (ArrayUtil.isNotEmpty(interfaces)) {
CollUtil.addAll(nextClasses, interfaces);
}
}
}
/**
* 若{@link #includeSuperClass}为{@code true},则将目标类的父类也添加到nextClasses
*
* @param nextClassQueue 下一个类队列
* @param targetClass 目标类型
*/
protected void scanSuperClassIfNecessary(List<Class<?>> nextClassQueue, Class<?> targetClass) {
if (includeSuperClass) {
final Class<?> superClass = targetClass.getSuperclass();
if (!ObjectUtil.equals(superClass, Object.class) && ObjectUtil.isNotNull(superClass)) {
nextClassQueue.add(superClass);
}
}
}
/**
* 若存在转换器,则使用转换器对目标类进行转换
*
* @param target 目标类
* @return 转换后的类
*/
protected Class<?> convert(Class<?> target) {
if (hasConverters) {
for (final UnaryOperator<Class<?>> converter : converters) {
target = converter.apply(target);
}
}
return target;
}
/**
* 若类型为jdk代理类,则尝试转换为原始被代理类
*/
public static class JdkProxyClassConverter implements UnaryOperator<Class<?>> {
@Override
public Class<?> apply(Class<?> sourceClass) {
return Proxy.isProxyClass(sourceClass) ? apply(sourceClass.getSuperclass()) : sourceClass;
}
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment