add methods and comment

This commit is contained in:
huangchengxing 2022-07-16 18:37:33 +08:00
parent c27c74f192
commit 4e5cc6c5d0
2 changed files with 175 additions and 115 deletions

View File

@ -3,6 +3,7 @@ package cn.hutool.core.annotation;
import cn.hutool.core.annotation.scanner.*;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.exceptions.UtilException;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
@ -315,104 +316,19 @@ public class AnnotationUtil {
return annotationType.isAnnotationPresent(Inherited.class);
}
/**
* 设置新的注解的属性字段
*
* @param annotation 注解对象
* @param annotationField 注解属性字段名称
* @param value 要更新的属性值
* @since 5.5.2
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public static void setValue(Annotation annotation, String annotationField, Object value) {
final Map memberValues = (Map) ReflectUtil.getFieldValue(Proxy.getInvocationHandler(annotation), "memberValues");
memberValues.put(annotationField, value);
}
/**
* 获取别名支持后的注解
*
* @param annotationEle 被注解的类
* @param annotationType 注解类型Class
* @param <T> 注解类型
* @return 别名支持后的注解
* @since 5.7.23
*/
@SuppressWarnings("unchecked")
public static <T extends Annotation> T getAnnotationAlias(AnnotatedElement annotationEle, Class<T> annotationType) {
final T annotation = getAnnotation(annotationEle, annotationType);
return (T) Proxy.newProxyInstance(annotationType.getClassLoader(), new Class[]{annotationType}, new AnnotationProxy<>(annotation));
}
/**
* 将指定注解实例与其元注解转为合成注解
*
* @param annotation 注解对象
* @param annotationType 注解类
* @param <T> 注解类型
* @return 合成注解
* @see SynthesizedAggregateAnnotation
*/
public static <T extends Annotation> T getSynthesizedAnnotation(Annotation annotation, Class<T> annotationType) {
// TODO 缓存合成注解信息避免重复解析
return aggregatingFromAnnotationWithMeta(annotation).synthesize(annotationType);
}
/**
* 获取元素上距离指定元素最接近的合成注解
* <ul>
* <li>若元素是类则递归解析全部父类和全部父接口上的注解;</li>
* <li>若元素是方法属性或注解则只解析其直接声明的注解;</li>
* </ul>
*
* @param annotatedEle {@link AnnotatedElement}可以是ClassMethodFieldConstructorReflectPermission
* @param annotationType 注解类
* @param <T> 注解类型
* @return 合成注解
* @see SynthesizedAggregateAnnotation
*/
public static <T extends Annotation> T getSynthesizedAnnotation(AnnotatedElement annotatedEle, Class<T> annotationType) {
T target = annotatedEle.getAnnotation(annotationType);
if (ObjectUtil.isNotNull(target)) {
return target;
}
AnnotationScanner[] scanners = new AnnotationScanner[]{
new MetaAnnotationScanner(), new TypeAnnotationScanner(), new MethodAnnotationScanner(), new FieldAnnotationScanner()
};
return AnnotationScanner.scanByAnySupported(annotatedEle, scanners).stream()
.map(annotation -> getSynthesizedAnnotation(annotation, annotationType))
.filter(Objects::nonNull)
.findFirst()
.orElse(null);
}
/**
* 获取元素上所有指定注解
* <ul>
* <li>若元素是类则递归解析全部父类和全部父接口上的注解;</li>
* <li>若元素是方法属性或注解则只解析其直接声明的注解;</li>
* </ul>
*
* @param annotatedEle {@link AnnotatedElement}可以是ClassMethodFieldConstructorReflectPermission
* @param annotationType 注解类
* @param <T> 注解类型
* @return 合成注解
* @see SynthesizedAggregateAnnotation
*/
public static <T extends Annotation> List<T> getAllSynthesizedAnnotations(AnnotatedElement annotatedEle, Class<T> annotationType) {
AnnotationScanner[] scanners = new AnnotationScanner[]{
new MetaAnnotationScanner(), new TypeAnnotationScanner(), new MethodAnnotationScanner(), new FieldAnnotationScanner()
};
return AnnotationScanner.scanByAnySupported(annotatedEle, scanners).stream()
.map(annotation -> getSynthesizedAnnotation(annotation, annotationType))
.filter(Objects::nonNull)
.collect(Collectors.toList());
}
/**
* 扫描注解类以及注解类的{@link Class}层级结构中的注解将返回除了{@link #META_ANNOTATIONS}中指定的JDK默认注解外
* 按元注解对象与{@code annotationType}的距离和{@link Class#getAnnotations()}顺序排序的注解对象集合
*
* <p>比如<br>
* {@code annotationType} A且A存在元注解BB又存在元注解C和D则有
* <pre>
* |-&gt; C.class [@a, @b]
* A.class -&gt; B.class [@a] -|
* |-&gt; D.class [@a, @c]
* </pre>
* 扫描A则该方法最终将返回 {@code [@a, @a, @b, @a, @c]}
*
* @param annotationType 注解类
* @return 注解对象集合
* @see MetaAnnotationScanner
@ -432,6 +348,16 @@ public class AnnotationUtil {
* </ul>
* 注解根据其声明类/接口被扫描的顺序排序若注解都在同一个{@link Class}中被声明则还会遵循{@link Class#getAnnotations()}的顺序
*
* <p>比如<br>
* {@code targetClass}{@code A.class}{@code A.class}存在父类{@code B.class}父接口{@code C.class}
* 三个类的注解声明情况如下
* <pre>
* |-&gt; B.class [@a, @b]
* A.class [@a] -|
* |-&gt; C.class [@a, @c]
* </pre>
* 则该方法最终将返回 {@code [@a, @a, @b, @a, @c]}
*
* @param targetClass
* @return 注解对象集合
* @see TypeAnnotationScanner
@ -452,6 +378,14 @@ public class AnnotationUtil {
* </ul>
* 方法上的注解根据方法的声明类/接口被扫描的顺序排序若注解都在同一个类的同一个方法中被声明则还会遵循{@link Method#getAnnotations()}的顺序
*
* <p>比如<br>
* 若方法X声明于{@code A.class}且重载/重写自父类{@code B.class}并且父类中的方法X由重写至其实现的接口{@code C.class}
* 三个类的注解声明情况如下
* <pre>
* A#X()[@a] -&gt; B#X()[@b] -&gt; C#X()[@c]
* </pre>
* 则该方法最终将返回 {@code [@a, @b, @c]}
*
* @param method 方法
* @return 注解对象集合
* @see MethodAnnotationScanner
@ -460,6 +394,152 @@ public class AnnotationUtil {
return new MethodAnnotationScanner(true).getIfSupport(method);
}
/**
* 设置新的注解的属性字段
*
* @param annotation 注解对象
* @param annotationField 注解属性字段名称
* @param value 要更新的属性值
* @since 5.5.2
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public static void setValue(Annotation annotation, String annotationField, Object value) {
final Map memberValues = (Map) ReflectUtil.getFieldValue(Proxy.getInvocationHandler(annotation), "memberValues");
memberValues.put(annotationField, value);
}
/**
* 该注解对象是否为通过代理类生成的合成注解
*
* @param annotation 注解对象
* @return 是否
* @see SynthesizedAnnotationProxy#isProxyAnnotation(Class)
*/
public static boolean isSynthesizedAnnotation(Annotation annotation) {
return SynthesizedAnnotationProxy.isProxyAnnotation(annotation.getClass());
}
/**
* 获取别名支持后的注解
*
* @param annotationEle 被注解的类
* @param annotationType 注解类型Class
* @param <T> 注解类型
* @return 别名支持后的注解
* @since 5.7.23
*/
public static <T extends Annotation> T getAnnotationAlias(AnnotatedElement annotationEle, Class<T> annotationType) {
final T annotation = getAnnotation(annotationEle, annotationType);
return aggregatingFromAnnotation(annotation).synthesize(annotationType);
}
/**
* 将指定注解实例与其元注解转为合成注解
*
* @param annotationType 注解类
* @param annotations 注解对象
* @param <T> 注解类型
* @return 合成注解
* @see SynthesizedAggregateAnnotation
*/
public static <T extends Annotation> T getSynthesizedAnnotation(Class<T> annotationType, Annotation... annotations) {
// TODO 缓存合成注解信息避免重复解析
return Opt.ofNullable(annotations)
.filter(ArrayUtil::isNotEmpty)
.map(AnnotationUtil::aggregatingFromAnnotationWithMeta)
.map(a -> a.synthesize(annotationType))
.get();
}
/**
* <p>获取元素上距离指定元素最接近的合成注解
* <ul>
* <li>若元素是类则递归解析全部父类和全部父接口上的注解;</li>
* <li>若元素是方法属性或注解则只解析其直接声明的注解;</li>
* </ul>
*
* <p>注解合成规则如下
* {@code AnnotatedEle}按顺序从上到下声明了ABC三个注解且三注解存在元注解如下
* <pre>
* A -&gt; MA1 -&gt; MA2
* B -&gt; MB1 -&gt; MB2
* C -&gt; MC1
* </pre>
* 此时入参{@code annotationType}类型为{@code MB1}则最终将优先返回基于根注解B合成的合成注解
*
* @param annotatedEle {@link AnnotatedElement}可以是ClassMethodFieldConstructorReflectPermission
* @param annotationType 注解类
* @param <T> 注解类型
* @return 合成注解
* @see SynthesizedAggregateAnnotation
*/
public static <T extends Annotation> T getSynthesizedAnnotation(AnnotatedElement annotatedEle, Class<T> annotationType) {
T target = annotatedEle.getAnnotation(annotationType);
if (ObjectUtil.isNotNull(target)) {
return target;
}
AnnotationScanner[] scanners = new AnnotationScanner[]{
new MetaAnnotationScanner(), new TypeAnnotationScanner(), new MethodAnnotationScanner(), new FieldAnnotationScanner()
};
return AnnotationScanner.scanByAnySupported(annotatedEle, scanners).stream()
.map(annotation -> getSynthesizedAnnotation(annotationType, annotation))
.filter(Objects::nonNull)
.findFirst()
.orElse(null);
}
/**
* 获取元素上所有指定注解
* <ul>
* <li>若元素是类则递归解析全部父类和全部父接口上的注解;</li>
* <li>若元素是方法属性或注解则只解析其直接声明的注解;</li>
* </ul>
*
* <p>注解合成规则如下
* {@code AnnotatedEle}按顺序从上到下声明了ABC三个注解且三注解存在元注解如下
* <pre>
* A -&gt; M1 -&gt; M2
* B -&gt; M3 -&gt; M1
* C -&gt; M2
* </pre>
* 此时入参{@code annotationType}类型为{@code M1}则最终将返回基于根注解A与根注解B合成的合成注解
*
* @param annotatedEle {@link AnnotatedElement}可以是ClassMethodFieldConstructorReflectPermission
* @param annotationType 注解类
* @param <T> 注解类型
* @return 合成注解
* @see SynthesizedAggregateAnnotation
*/
public static <T extends Annotation> List<T> getAllSynthesizedAnnotations(AnnotatedElement annotatedEle, Class<T> annotationType) {
AnnotationScanner[] scanners = new AnnotationScanner[]{
new MetaAnnotationScanner(), new TypeAnnotationScanner(), new MethodAnnotationScanner(), new FieldAnnotationScanner()
};
return AnnotationScanner.scanByAnySupported(annotatedEle, scanners).stream()
.map(annotation -> getSynthesizedAnnotation(annotationType, annotation))
.filter(Objects::nonNull)
.collect(Collectors.toList());
}
/**
* 对指定注解对象进行聚合
*
* @param annotations 注解对象
* @return 聚合注解
*/
public static SynthesizedAggregateAnnotation aggregatingFromAnnotation(Annotation... annotations) {
return new GenericSynthesizedAggregateAnnotation(Arrays.asList(annotations), EmptyAnnotationScanner.INSTANCE);
}
/**
* 对指定注解对象及其元注解进行聚合
*
* @param annotations 注解对象
* @return 聚合注解
*/
public static SynthesizedAggregateAnnotation aggregatingFromAnnotationWithMeta(Annotation... annotations) {
return new GenericSynthesizedAggregateAnnotation(Arrays.asList(annotations), new MetaAnnotationScanner());
}
/**
* 方法是否为注解属性方法 <br>
* 方法无参数且有返回值的方法认为是注解属性的方法
@ -470,24 +550,4 @@ public class AnnotationUtil {
return method.getParameterCount() == 0 && method.getReturnType() != void.class;
}
/**
* 对指定注解对象进行聚合
*
* @param annotation 注解对象
* @return 聚合注解
*/
static SynthesizedAggregateAnnotation aggregatingFromAnnotation(Annotation annotation) {
return new GenericSynthesizedAggregateAnnotation(Collections.singletonList(annotation), EmptyAnnotationScanner.INSTANCE);
}
/**
* 对指定注解对象及其元注解进行聚合
*
* @param annotation 注解对象
* @return 聚合注解
*/
static SynthesizedAggregateAnnotation aggregatingFromAnnotationWithMeta(Annotation annotation) {
return new GenericSynthesizedAggregateAnnotation(annotation);
}
}

View File

@ -19,7 +19,7 @@ import java.util.stream.Stream;
* @param <T> 注解类型
* @author huangchengxing
*/
public class GenericSynthesizedAnnotation<R, T extends Annotation> implements Annotation, SynthesizedAnnotation {
public class GenericSynthesizedAnnotation<R, T extends Annotation> implements SynthesizedAnnotation {
private final R root;
private final T annotation;