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.captcha;
import cn.hutool.captcha.generator.MathGenerator;
import org.junit.Test;
public class GeneratorTest {
@Test
public void mathGeneratorTest() {
final MathGenerator mathGenerator = new MathGenerator();
for (int i = 0; i < 1000; i++) {
mathGenerator.verify(mathGenerator.generate(), "0");
}
}
}
<p align="center">
<a href="https://hutool.cn/"><img src="https://cdn.jsdelivr.net/gh/looly/hutool-site/images/logo.jpg" width="45%"></a>
</p>
<p align="center">
<strong>🍬A set of tools that keep Java sweet.</strong>
</p>
<p align="center">
👉 <a href="https://hutool.cn">https://hutool.cn/</a> 👈
</p>
## 📚Hutool-core 模块介绍
`Hutool-core`提供了最常使用的基础工具类,包括集合、Map、IO、线程、Bean、图片处理、线程并发等便捷工具。
-------------------------------------------------------------------------------
## 🛠️包含内容
### 注解(annotation)
提供了注解工具类,以及一些注解封装。如`CombinationAnnotationElement`组合注解以及Alias别名注解等。
### bean(bean)
提供了Bean工具类,以及Bean属性解析、Bean拷贝、动态Bean等。
### 构建器(builder)
抽象了Builder接口,提供建造者模式的封装,并默认提供了包括equals封装、Bean构建封装、比较器封装等。
### 克隆(clone)
提供`Cloneable`接口,明确`clone`方法,并提供默认实现类。
### 编码(codec)
提供了BaseN编码(Base16、Base32、Base58、Base62、Base64)编码实现。并提供了包括BCD、PunyCode、百分号编码的实现。
同时提供了包括莫尔斯电码、凯撒密码、RotN这类有趣功能的实现。
### 集合(collection)
集合中主要是提供了针对`Iterator`实现类的工具封装方法`IterUtil`和集合类封装的工具类`CollUtil`,并提供了一些特别的集合封装。
### 比较器(comparator)
主要是一些比较器的实现,如Bean字段比较器、自定义函数比较器、版本比较器等。
### 动态编译(compiler)
提供`javax.tools.JavaCompiler`的包装简化服务,形成源码动态编译工具类`CompilerUtil`,完成代码动态编译及热部署。
### 压缩(compress)
主要针对`java.util.zip`中的相关类封装工具,提供Zip、Gzip、Zlib等格式的压缩解压缩封装,为`ZipUtil`提供服务。
### 转换(convert)
“万能”转换器,提供整套的类型转换方式。通过`Converter`接口和`ConverterRegistry`转换登记中心,完成任意数据类型转换和自定义转换。
### 日期时间(date)
提供`Date``Calendar``java.time`相关API的工具化封装。包括时间解析、格式化、偏移等。
### 异常(exceptions)
提供异常工具`ExceptionUtil`,以及一些工具内部使用的异常。
### getter接口(getter)
提供各种类型的get操作接口封装。
### 图片(img)
提供图片、绘图、字体等工具封装,并提供GIF生成器和解析器实现。
### IO流和文件(io)
提供IO流工具、文件工具、文件类型工具等,并提供流拷贝、Checksum、文件监听功能实现。
### 语言特性(lang)
超级大杂项,提供一些设计模式的抽象实现(如单例模式`Singleton`),还有正则、Id生成器、函数、Hash算法、可变对象、树形结构、字典等。
### Map(map)
提供Map工具类和各类Map实现封装,如行列键的Table实现、自定义键值对转换的Map、线程安全的WeakMap实现等。
### 数学(math)
提供简单数学计算封装,如排列组合、货币类等。
### 网络(net)
提供网络相关工具封装,以及Ip地址工具类、SSL工具类、URL编码解码等。
### StreamAPI封装(stream)
提供简单的Stream相关封装。
### Swing和AWT(swing)
提供桌面应用API的工具封装,如启动应用、控制键盘鼠标操作、截屏等功能。
### 文本字符串(text)
提供强大的字符串文本封装,包括字符转换、字符串查找、字符串替换、字符串切分、Unicode工具等,并提供CSV格式封装。
### 线程及并发(thread)
线程并发封装,包括线程工具、锁工具、`CompletableFuture`封装工具、线程池构建等。
### 工具杂项(util)
提供其他不便归类的杂项工具类。如数组、编码、字符、Class、坐标系、身份证、组织机构代码、脱敏、枚举、转义、XML、进制转换、随机数、反射、正则、SPI等各种工具。
\ No newline at end of file
<?xml version='1.0' encoding='utf-8'?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.8.19</version>
</parent>
<artifactId>hutool-core</artifactId>
<name>${project.artifactId}</name>
<description>Hutool核心,包括集合、字符串、Bean等工具</description>
<properties>
<Automatic-Module-Name>cn.hutool.core</Automatic-Module-Name>
</properties>
</project>
package cn.hutool.core.annotation;
import cn.hutool.core.annotation.scanner.AnnotationScanner;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import java.lang.annotation.Annotation;
import java.util.Collection;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* {@link AnnotationSynthesizer}的基本实现
*
* @author huangchengxing
*/
public abstract class AbstractAnnotationSynthesizer<T> implements AnnotationSynthesizer {
/**
* 合成注解来源最初来源
*/
protected final T source;
/**
* 包含根注解以及其元注解在内的全部注解实例
*/
protected final Map<Class<? extends Annotation>, SynthesizedAnnotation> synthesizedAnnotationMap;
/**
* 已经合成过的注解对象
*/
private final Map<Class<? extends Annotation>, Annotation> synthesizedProxyAnnotations;
/**
* 合成注解选择器
*/
protected final SynthesizedAnnotationSelector annotationSelector;
/**
* 合成注解属性处理器
*/
protected final Collection<SynthesizedAnnotationPostProcessor> postProcessors;
/**
* 注解扫描器
*/
protected final AnnotationScanner annotationScanner;
/**
* 构造一个注解合成器
*
* @param source 当前查找的注解对象
* @param annotationSelector 合成注解选择器
* @param annotationPostProcessors 注解后置处理器
* @param annotationScanner 注解扫描器,该扫描器需要支持扫描注解类
*/
protected AbstractAnnotationSynthesizer(
T source,
SynthesizedAnnotationSelector annotationSelector,
Collection<SynthesizedAnnotationPostProcessor> annotationPostProcessors,
AnnotationScanner annotationScanner) {
Assert.notNull(source, "source must not null");
Assert.notNull(annotationSelector, "annotationSelector must not null");
Assert.notNull(annotationPostProcessors, "annotationPostProcessors must not null");
Assert.notNull(annotationPostProcessors, "annotationScanner must not null");
this.source = source;
this.annotationSelector = annotationSelector;
this.annotationScanner = annotationScanner;
this.postProcessors = CollUtil.unmodifiable(
CollUtil.sort(annotationPostProcessors, Comparator.comparing(SynthesizedAnnotationPostProcessor::order))
);
this.synthesizedProxyAnnotations = new LinkedHashMap<>();
this.synthesizedAnnotationMap = MapUtil.unmodifiable(loadAnnotations());
annotationPostProcessors.forEach(processor ->
synthesizedAnnotationMap.values().forEach(synthesized -> processor.process(synthesized, this))
);
}
/**
* 加载合成注解的必要属性
*
* @return 合成注解
*/
protected abstract Map<Class<? extends Annotation>, SynthesizedAnnotation> loadAnnotations();
/**
* 根据指定的注解类型和对应注解对象,合成最终所需的合成注解
*
* @param annotationType 注解类型
* @param annotation 合成注解对象
* @param <A> 注解类型
* @return 最终所需的合成注解
*/
protected abstract <A extends Annotation> A synthesize(Class<A> annotationType, SynthesizedAnnotation annotation);
/**
* 获取合成注解来源最初来源
*
* @return 合成注解来源最初来源
*/
@Override
public T getSource() {
return source;
}
/**
* 合成注解选择器
*
* @return 注解选择器
*/
@Override
public SynthesizedAnnotationSelector getAnnotationSelector() {
return annotationSelector;
}
/**
* 获取合成注解后置处理器
*
* @return 合成注解后置处理器
*/
@Override
public Collection<SynthesizedAnnotationPostProcessor> getAnnotationPostProcessors() {
return postProcessors;
}
/**
* 获取已合成的注解
*
* @param annotationType 注解类型
* @return 已合成的注解
*/
@Override
public SynthesizedAnnotation getSynthesizedAnnotation(Class<?> annotationType) {
return synthesizedAnnotationMap.get(annotationType);
}
/**
* 获取全部的合成注解
*
* @return 合成注解
*/
@Override
public Map<Class<? extends Annotation>, SynthesizedAnnotation> getAllSynthesizedAnnotation() {
return synthesizedAnnotationMap;
}
/**
* 获取合成注解
*
* @param annotationType 注解类型
* @param <A> 注解类型
* @return 类型
*/
@SuppressWarnings("unchecked")
@Override
public <A extends Annotation> A synthesize(Class<A> annotationType) {
return (A)synthesizedProxyAnnotations.computeIfAbsent(annotationType, type -> {
final SynthesizedAnnotation synthesizedAnnotation = synthesizedAnnotationMap.get(annotationType);
return ObjectUtil.isNull(synthesizedAnnotation) ?
null : synthesize(annotationType, synthesizedAnnotation);
});
}
}
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 SynthesizedAggregateAnnotation}中存在,
* 则从聚合器中获取类型对应的合成注解对象,与该对象中的指定属性,然后将全部关联数据交给
* {@link #processLinkedAttribute}处理。
*
* @param synthesizedAnnotation 合成的注解
* @param synthesizer 合成注解聚合器
*/
@Override
public void process(SynthesizedAnnotation synthesizedAnnotation, AnnotationSynthesizer synthesizer) {
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, synthesizer, synthesizedAnnotation.annotationType());
if (ObjectUtil.isNull(linkedAnnotation)) {
return;
}
final AnnotationAttribute linkedAttribute = linkedAnnotation.getAttributes().get(link.attribute());
// 处理
processLinkedAttribute(
synthesizer, link,
synthesizedAnnotation, synthesizedAnnotation.getAttributes().get(originalAttributeName),
linkedAnnotation, linkedAttribute
);
});
}
// =========================== 抽象方法 ===========================
/**
* 当属性上存在{@link Link}注解时,仅当{@link Link#type()}在本方法返回值内存在时才进行处理
*
* @return 支持处理的{@link RelationType}类型
*/
protected abstract RelationType[] processTypes();
/**
* 对关联的合成注解对象及其关联属性的处理
*
* @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}中的关联属性,该参数可能为空
*/
protected abstract void processLinkedAttribute(
AnnotationSynthesizer synthesizer, 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 synthesizer 注解合成器
* @param defaultType 默认类型
* @return {@link SynthesizedAnnotation}
*/
protected SynthesizedAnnotation getLinkedAnnotation(Link annotation, AnnotationSynthesizer synthesizer, Class<? extends Annotation> defaultType) {
final Class<?> targetAnnotationType = getLinkedAnnotationType(annotation, defaultType);
return synthesizer.getSynthesizedAnnotation(targetAnnotationType);
}
/**
* 若{@link Link#annotation()}获取的类型{@code 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())
);
}
}
package cn.hutool.core.annotation;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* {@link WrappedAnnotationAttribute}的基本实现
*
* @author huangchengxing
* @see ForceAliasedAnnotationAttribute
* @see AliasedAnnotationAttribute
* @see MirroredAnnotationAttribute
*/
public abstract class AbstractWrappedAnnotationAttribute implements WrappedAnnotationAttribute {
protected final AnnotationAttribute original;
protected final AnnotationAttribute linked;
protected AbstractWrappedAnnotationAttribute(AnnotationAttribute original, AnnotationAttribute linked) {
Assert.notNull(original, "target must not null");
Assert.notNull(linked, "linked must not null");
this.original = original;
this.linked = linked;
}
@Override
public AnnotationAttribute getOriginal() {
return original;
}
@Override
public AnnotationAttribute getLinked() {
return linked;
}
@Override
public AnnotationAttribute getNonWrappedOriginal() {
AnnotationAttribute curr = null;
AnnotationAttribute next = original;
while (next != null) {
curr = next;
next = next.isWrapped() ? ((WrappedAnnotationAttribute)curr).getOriginal() : null;
}
return curr;
}
@Override
public Collection<AnnotationAttribute> getAllLinkedNonWrappedAttributes() {
List<AnnotationAttribute> leafAttributes = new ArrayList<>();
collectLeafAttribute(this, leafAttributes);
return leafAttributes;
}
private void collectLeafAttribute(AnnotationAttribute curr, List<AnnotationAttribute> leafAttributes) {
if (ObjectUtil.isNull(curr)) {
return;
}
if (!curr.isWrapped()) {
leafAttributes.add(curr);
return;
}
WrappedAnnotationAttribute wrappedAttribute = (WrappedAnnotationAttribute)curr;
collectLeafAttribute(wrappedAttribute.getOriginal(), leafAttributes);
collectLeafAttribute(wrappedAttribute.getLinked(), leafAttributes);
}
}
package cn.hutool.core.annotation;
import java.lang.annotation.Annotation;
/**
* 表示一组被聚合在一起的注解对象
*
* @author huangchengxing
*/
public interface AggregateAnnotation extends Annotation {
/**
* 在聚合中是否存在的指定类型注解对象
*
* @param annotationType 注解类型
* @return 是否
*/
boolean isAnnotationPresent(Class<? extends Annotation> annotationType);
/**
* 获取聚合中的全部注解对象
*
* @return 注解对象
*/
Annotation[] getAnnotations();
}
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等
*
* @author Looly
* @since 5.1.1
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
public @interface Alias {
/**
* 别名值,即使用此注解要替换成的别名名称
*
* @return 别名值
*/
String value();
}
package cn.hutool.core.annotation;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.map.ForestMap;
import cn.hutool.core.map.LinkedForestMap;
import cn.hutool.core.map.TreeEntry;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ObjectUtil;
import java.util.Map;
/**
* <p>用于处理注解对象中带有{@link Alias}注解的属性。<br>
* 当该处理器执行完毕后,{@link Alias}注解指向的目标注解的属性将会被包装并替换为
* {@link ForceAliasedAnnotationAttribute}。
*
* @author huangchengxing
* @see Alias
* @see ForceAliasedAnnotationAttribute
*/
public class AliasAnnotationPostProcessor implements SynthesizedAnnotationPostProcessor {
@Override
public int order() {
return Integer.MIN_VALUE;
}
@Override
public void process(SynthesizedAnnotation synthesizedAnnotation, AnnotationSynthesizer synthesizer) {
final Map<String, AnnotationAttribute> attributeMap = synthesizedAnnotation.getAttributes();
// 记录别名与属性的关系
final ForestMap<String, AnnotationAttribute> attributeAliasMappings = new LinkedForestMap<>(false);
attributeMap.forEach((attributeName, attribute) -> {
final String alias = Opt.ofNullable(attribute.getAnnotation(Alias.class))
.map(Alias::value)
.orElse(null);
if (ObjectUtil.isNull(alias)) {
return;
}
final AnnotationAttribute aliasAttribute = attributeMap.get(alias);
Assert.notNull(aliasAttribute, "no method for alias: [{}]", alias);
attributeAliasMappings.putLinkedNodes(alias, aliasAttribute, attributeName, attribute);
});
// 处理别名
attributeMap.forEach((attributeName, attribute) -> {
final AnnotationAttribute resolvedAttribute = Opt.ofNullable(attributeName)
.map(attributeAliasMappings::getRootNode)
.map(TreeEntry::getValue)
.orElse(attribute);
Assert.isTrue(
ObjectUtil.isNull(resolvedAttribute)
|| ClassUtil.isAssignable(attribute.getAttributeType(), resolvedAttribute.getAttributeType()),
"return type of the root alias method [{}] is inconsistent with the original [{}]",
resolvedAttribute.getClass(), attribute.getAttributeType()
);
if (attribute != resolvedAttribute) {
attributeMap.put(attributeName, new ForceAliasedAnnotationAttribute(attribute, resolvedAttribute));
}
});
synthesizedAnnotation.setAttributes(attributeMap);
}
}
package cn.hutool.core.annotation;
import java.lang.annotation.*;
/**
* <p>{@link Link}的子注解。表示“原始属性”将作为“关联属性”的别名。
* <ul>
* <li>当“原始属性”为默认值时,获取“关联属性”将返回“关联属性”本身的值;</li>
* <li>当“原始属性”不为默认值时,获取“关联属性”将返回“原始属性”的值;</li>
* </ul>
* <b>注意,该注解与{@link Link}、{@link ForceAliasFor}或{@link MirrorFor}一起使用时,将只有被声明在最上面的注解会生效</b>
*
* @author huangchengxing
* @see Link
* @see RelationType#ALIAS_FOR
*/
@Link(type = RelationType.ALIAS_FOR)
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
public @interface AliasFor {
/**
* 产生关联的注解类型,当不指定时,默认指注释的属性所在的类
*
* @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.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 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) {
// 校验别名关系
checkAliasRelation(annotation, originalAttribute, linkedAttribute);
// 处理aliasFor类型的关系
if (RelationType.ALIAS_FOR.equals(annotation.type())) {
wrappingLinkedAttribute(synthesizer, originalAttribute, linkedAttribute, AliasedAnnotationAttribute::new);
return;
}
// 处理forceAliasFor类型的关系
wrappingLinkedAttribute(synthesizer, originalAttribute, linkedAttribute, ForceAliasedAnnotationAttribute::new);
}
/**
* 对指定注解属性进行包装,若该属性已被包装过,则递归以其为根节点的树结构,对树上全部的叶子节点进行包装
*/
private void wrappingLinkedAttribute(
AnnotationSynthesizer synthesizer, AnnotationAttribute originalAttribute, AnnotationAttribute aliasAttribute, BinaryOperator<AnnotationAttribute> wrapping) {
// 不是包装属性
if (!aliasAttribute.isWrapped()) {
processAttribute(synthesizer, originalAttribute, aliasAttribute, wrapping);
return;
}
// 是包装属性
final AbstractWrappedAnnotationAttribute wrapper = (AbstractWrappedAnnotationAttribute)aliasAttribute;
wrapper.getAllLinkedNonWrappedAttributes().forEach(
t -> processAttribute(synthesizer, originalAttribute, t, wrapping)
);
}
/**
* 获取指定注解属性,然后将其再进行一层包装
*/
private void processAttribute(
AnnotationSynthesizer synthesizer, AnnotationAttribute originalAttribute,
AnnotationAttribute target, BinaryOperator<AnnotationAttribute> wrapping) {
Opt.ofNullable(target.getAnnotationType())
.map(synthesizer::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()
);
}
}
package cn.hutool.core.annotation;
/**
* <p>表示一个具有别名的属性。
* 当别名属性值为默认值时,优先返回原属性的值,当别名属性不为默认值时,优先返回别名属性的值
*
* @author huangchengxing
* @see AliasLinkAnnotationPostProcessor
* @see RelationType#ALIAS_FOR
*/
public class AliasedAnnotationAttribute extends AbstractWrappedAnnotationAttribute {
protected AliasedAnnotationAttribute(AnnotationAttribute origin, AnnotationAttribute linked) {
super(origin, linked);
}
/**
* 若{@link #linked}为默认值,则返回{@link #original}的值,否则返回{@link #linked}的值
*
* @return 属性值
*/
@Override
public Object getValue() {
return linked.isValueEquivalentToDefaultValue() ? super.getValue() : linked.getValue();
}
/**
* 当{@link #original}与{@link #linked}都为默认值时返回{@code true}
*
* @return 是否
*/
@Override
public boolean isValueEquivalentToDefaultValue() {
return linked.isValueEquivalentToDefaultValue() && original.isValueEquivalentToDefaultValue();
}
}
package cn.hutool.core.annotation;
import cn.hutool.core.util.ReflectUtil;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
/**
* <p>表示注解的某个属性,等同于绑定的调用对象的{@link Method}方法。<br>
* 在{@link SynthesizedAggregateAnnotation}的解析以及取值过程中,
* 可以通过设置{@link SynthesizedAnnotation}的注解属性,
* 从而使得可以从一个注解对象中属性获取另一个注解对象的属性值
*
* <p>一般情况下,注解属性的处理会发生在{@link SynthesizedAnnotationPostProcessor}调用时
*
* @author huangchengxing
* @see SynthesizedAnnotationPostProcessor
* @see WrappedAnnotationAttribute
* @see CacheableAnnotationAttribute
* @see AbstractWrappedAnnotationAttribute
* @see ForceAliasedAnnotationAttribute
* @see AliasedAnnotationAttribute
* @see MirroredAnnotationAttribute
*/
public interface AnnotationAttribute {
/**
* 获取注解对象
*
* @return 注解对象
*/
Annotation getAnnotation();
/**
* 获取注解属性对应的方法
*
* @return 注解属性对应的方法
*/
Method getAttribute();
/**
* 获取声明属性的注解类
*
* @return 声明注解的注解类
*/
default Class<?> getAnnotationType() {
return getAttribute().getDeclaringClass();
}
/**
* 获取属性名称
*
* @return 属性名称
*/
default String getAttributeName() {
return getAttribute().getName();
}
/**
* 获取注解属性
*
* @return 注解属性
*/
default Object getValue() {
return ReflectUtil.invoke(getAnnotation(), getAttribute());
}
/**
* 该注解属性的值是否等于默认值
*
* @return 该注解属性的值是否等于默认值
*/
boolean isValueEquivalentToDefaultValue();
/**
* 获取属性类型
*
* @return 属性类型
*/
default Class<?> getAttributeType() {
return getAttribute().getReturnType();
}
/**
* 获取属性上的注解
*
* @param <T> 注解类型
* @param annotationType 注解类型
* @return 注解对象
*/
default <T extends Annotation> T getAnnotation(Class<T> annotationType) {
return getAttribute().getAnnotation(annotationType);
}
/**
* 当前注解属性是否已经被{@link WrappedAnnotationAttribute}包装
*
* @return boolean
*/
default boolean isWrapped() {
return false;
}
}
package cn.hutool.core.annotation;
/**
* 表示一个可以从当前接口的实现类中,获得特定的属性值
*/
@FunctionalInterface
public interface AnnotationAttributeValueProvider {
/**
* 获取注解属性值
*
* @param attributeName 属性名称
* @param attributeType 属性类型
* @return 注解属性值
*/
Object getAttributeValue(String attributeName, Class<?> attributeType);
}
package cn.hutool.core.annotation;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
/**
* 注解代理<br>
* 通过代理指定注解,可以自定义调用注解的方法逻辑,如支持{@link Alias} 注解
*
* @param <T> 注解类型
* @since 5.7.23
*/
public class AnnotationProxy<T extends Annotation> implements Annotation, InvocationHandler, Serializable {
private static final long serialVersionUID = 1L;
private final T annotation;
private final Class<T> type;
private final Map<String, Object> attributes;
/**
* 构造
*
* @param annotation 注解
*/
public AnnotationProxy(T annotation) {
this.annotation = annotation;
//noinspection unchecked
this.type = (Class<T>) annotation.annotationType();
this.attributes = initAttributes();
}
@Override
public Class<? extends Annotation> annotationType() {
return type;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 注解别名
Alias alias = method.getAnnotation(Alias.class);
if(null != alias){
final String name = alias.value();
if(StrUtil.isNotBlank(name)){
if(false == attributes.containsKey(name)){
throw new IllegalArgumentException(StrUtil.format("No method for alias: [{}]", name));
}
return attributes.get(name);
}
}
final Object value = attributes.get(method.getName());
if (value != null) {
return value;
}
return method.invoke(this, args);
}
/**
* 初始化注解的属性<br>
* 此方法预先调用所有注解的方法,将注解方法值缓存于attributes中
*
* @return 属性(方法结果)映射
*/
private Map<String, Object> initAttributes() {
final Method[] methods = ReflectUtil.getMethods(this.type);
final Map<String, Object> attributes = new HashMap<>(methods.length, 1);
for (Method method : methods) {
// 跳过匿名内部类自动生成的方法
if (method.isSynthetic()) {
continue;
}
attributes.put(method.getName(), ReflectUtil.invoke(this.annotation, method));
}
return attributes;
}
}
package cn.hutool.core.annotation;
import java.lang.annotation.Annotation;
import java.util.Collection;
import java.util.Map;
/**
* <p>注解合成器,用于处理一组给定的与{@link #getSource()}具有直接或间接联系的注解对象,
* 并返回与原始注解对象具有不同属性的“合成”注解。
*
* <p>合成注解一般被用于处理类层级结果中具有直接或间接关联的注解对象,
* 当实例被创建时,会获取到这些注解对象,并使用{@link SynthesizedAnnotationSelector}对类型相同的注解进行过滤,
* 并最终得到类型不重复的有效注解对象。这些有效注解将被包装为{@link SynthesizedAnnotation},
* 然后最终用于“合成”一个{@link SynthesizedAggregateAnnotation}。<br>
* {@link SynthesizedAnnotationSelector}是合成注解生命周期中的第一个钩子,
* 自定义选择器以拦截原始注解被扫描的过程。
*
* <p>当合成注解完成对待合成注解的扫描,并完成了必要属性的加载后,
* 将会按顺序依次调用{@link SynthesizedAnnotationPostProcessor},
* 注解后置处理器允许用于对完成注解的待合成注解进行二次调整,
* 该钩子一般用于根据{@link Link}注解对属性进行调整。<br>
* {@link SynthesizedAnnotationPostProcessor}是合成注解生命周期中的第二个钩子,
* 自定义后置处理器以拦截原始在转为待合成注解后的初始化过程。
*
* <p>使用{@link #synthesize(Class)}用于获取“合成”后的注解,
* 该注解对象的属性可能会与原始的对象属性不同。
*
* @author huangchengxing
*/
public interface AnnotationSynthesizer {
/**
* 获取合成注解来源最初来源
*
* @return 合成注解来源最初来源
*/
Object getSource();
/**
* 合成注解选择器
*
* @return 注解选择器
*/
SynthesizedAnnotationSelector getAnnotationSelector();
/**
* 获取合成注解后置处理器
*
* @return 合成注解后置处理器
*/
Collection<SynthesizedAnnotationPostProcessor> getAnnotationPostProcessors();
/**
* 获取已合成的注解
*
* @param annotationType 注解类型
* @return 已合成的注解
*/
SynthesizedAnnotation getSynthesizedAnnotation(Class<?> annotationType);
/**
* 获取全部的合成注解
*
* @return 合成注解
*/
Map<Class<? extends Annotation>, SynthesizedAnnotation> getAllSynthesizedAnnotation();
/**
* 获取合成注解
*
* @param annotationType 注解类型
* @param <T> 注解类型
* @return 类型
*/
<T extends Annotation> T synthesize(Class<T> annotationType);
}
package cn.hutool.core.annotation;
import cn.hutool.core.annotation.scanner.AnnotationScanner;
import cn.hutool.core.annotation.scanner.MetaAnnotationScanner;
import cn.hutool.core.annotation.scanner.MethodAnnotationScanner;
import cn.hutool.core.annotation.scanner.TypeAnnotationScanner;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.exceptions.UtilException;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.lang.func.Func1;
import cn.hutool.core.lang.func.LambdaUtil;
import cn.hutool.core.util.*;
import java.lang.annotation.*;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
* 注解工具类<br>
* 快速获取注解对象、注解值等工具封装
*
* @author looly
* @since 4.0.9
*/
public class AnnotationUtil {
/**
* 元注解
*/
static final Set<Class<? extends Annotation>> META_ANNOTATIONS = CollUtil.newHashSet(Target.class, //
Retention.class, //
Inherited.class, //
Documented.class, //
SuppressWarnings.class, //
Override.class, //
Deprecated.class//
);
/**
* 是否为Jdk自带的元注解。<br>
* 包括:
* <ul>
* <li>{@link Target}</li>
* <li>{@link Retention}</li>
* <li>{@link Inherited}</li>
* <li>{@link Documented}</li>
* <li>{@link SuppressWarnings}</li>
* <li>{@link Override}</li>
* <li>{@link Deprecated}</li>
* </ul>
*
* @param annotationType 注解类型
* @return 是否为Jdk自带的元注解
*/
public static boolean isJdkMetaAnnotation(Class<? extends Annotation> annotationType) {
return META_ANNOTATIONS.contains(annotationType);
}
/**
* 是否不为Jdk自带的元注解。<br>
* 包括:
* <ul>
* <li>{@link Target}</li>
* <li>{@link Retention}</li>
* <li>{@link Inherited}</li>
* <li>{@link Documented}</li>
* <li>{@link SuppressWarnings}</li>
* <li>{@link Override}</li>
* <li>{@link Deprecated}</li>
* </ul>
*
* @param annotationType 注解类型
* @return 是否为Jdk自带的元注解
*/
public static boolean isNotJdkMateAnnotation(Class<? extends Annotation> annotationType) {
return false == isJdkMetaAnnotation(annotationType);
}
/**
* 将指定的被注解的元素转换为组合注解元素
*
* @param annotationEle 注解元素
* @return 组合注解元素
*/
public static CombinationAnnotationElement toCombination(AnnotatedElement annotationEle) {
if (annotationEle instanceof CombinationAnnotationElement) {
return (CombinationAnnotationElement) annotationEle;
}
return new CombinationAnnotationElement(annotationEle);
}
/**
* 获取指定注解
*
* @param annotationEle {@link AnnotatedElement},可以是Class、Method、Field、Constructor、ReflectPermission
* @param isToCombination 是否为转换为组合注解,组合注解可以递归获取注解的注解
* @return 注解对象
*/
public static Annotation[] getAnnotations(AnnotatedElement annotationEle, boolean isToCombination) {
return getAnnotations(annotationEle, isToCombination, (Predicate<Annotation>) null);
}
/**
* 获取组合注解
*
* @param <T> 注解类型
* @param annotationEle {@link AnnotatedElement},可以是Class、Method、Field、Constructor、ReflectPermission
* @param annotationType 限定的
* @return 注解对象数组
* @since 5.8.0
*/
public static <T> T[] getCombinationAnnotations(AnnotatedElement annotationEle, Class<T> annotationType) {
return getAnnotations(annotationEle, true, annotationType);
}
/**
* 获取指定注解
*
* @param <T> 注解类型
* @param annotationEle {@link AnnotatedElement},可以是Class、Method、Field、Constructor、ReflectPermission
* @param isToCombination 是否为转换为组合注解,组合注解可以递归获取注解的注解
* @param annotationType 限定的
* @return 注解对象数组
* @since 5.8.0
*/
public static <T> T[] getAnnotations(AnnotatedElement annotationEle, boolean isToCombination, Class<T> annotationType) {
final Annotation[] annotations = getAnnotations(annotationEle, isToCombination,
(annotation -> null == annotationType || annotationType.isAssignableFrom(annotation.getClass())));
final T[] result = ArrayUtil.newArray(annotationType, annotations.length);
for (int i = 0; i < annotations.length; i++) {
//noinspection unchecked
result[i] = (T) annotations[i];
}
return result;
}
/**
* 获取指定注解
*
* @param annotationEle {@link AnnotatedElement},可以是Class、Method、Field、Constructor、ReflectPermission
* @param isToCombination 是否为转换为组合注解,组合注解可以递归获取注解的注解
* @param predicate 过滤器,{@link Predicate#test(Object)}返回{@code true}保留,否则不保留
* @return 注解对象,如果提供的{@link AnnotatedElement}为{@code null},返回{@code null}
* @since 5.8.0
*/
public static Annotation[] getAnnotations(AnnotatedElement annotationEle, boolean isToCombination, Predicate<Annotation> predicate) {
if (null == annotationEle) {
return null;
}
if (isToCombination) {
if (null == predicate) {
return toCombination(annotationEle).getAnnotations();
}
return CombinationAnnotationElement.of(annotationEle, predicate).getAnnotations();
}
final Annotation[] result = annotationEle.getAnnotations();
if (null == predicate) {
return result;
}
return ArrayUtil.filter(result, predicate::test);
}
/**
* 获取指定注解
*
* @param <A> 注解类型
* @param annotationEle {@link AnnotatedElement},可以是Class、Method、Field、Constructor、ReflectPermission
* @param annotationType 注解类型
* @return 注解对象
*/
public static <A extends Annotation> A getAnnotation(AnnotatedElement annotationEle, Class<A> annotationType) {
return (null == annotationEle) ? null : toCombination(annotationEle).getAnnotation(annotationType);
}
/**
* 检查是否包含指定注解指定注解
*
* @param annotationEle {@link AnnotatedElement},可以是Class、Method、Field、Constructor、ReflectPermission
* @param annotationType 注解类型
* @return 是否包含指定注解
* @since 5.4.2
*/
public static boolean hasAnnotation(AnnotatedElement annotationEle, Class<? extends Annotation> annotationType) {
return null != getAnnotation(annotationEle, annotationType);
}
/**
* 获取指定注解默认值<br>
* 如果无指定的属性方法返回null
*
* @param <T> 注解值类型
* @param annotationEle {@link AnnotatedElement},可以是Class、Method、Field、Constructor、ReflectPermission
* @param annotationType 注解类型
* @return 注解对象
* @throws UtilException 调用注解中的方法时执行异常
*/
public static <T> T getAnnotationValue(AnnotatedElement annotationEle, Class<? extends Annotation> annotationType) throws UtilException {
return getAnnotationValue(annotationEle, annotationType, "value");
}
/**
* 获取指定注解属性的值<br>
* 如果无指定的属性方法返回null
*
* @param <T> 注解值类型
* @param annotationEle {@link AnnotatedElement},可以是Class、Method、Field、Constructor、ReflectPermission
* @param annotationType 注解类型
* @param propertyName 属性名,例如注解中定义了name()方法,则 此处传入name
* @return 注解对象
* @throws UtilException 调用注解中的方法时执行异常
*/
public static <T> T getAnnotationValue(AnnotatedElement annotationEle, Class<? extends Annotation> annotationType, String propertyName) throws UtilException {
final Annotation annotation = getAnnotation(annotationEle, annotationType);
if (null == annotation) {
return null;
}
final Method method = ReflectUtil.getMethodOfObj(annotation, propertyName);
if (null == method) {
return null;
}
return ReflectUtil.invoke(annotation, method);
}
/**
* 获取指定注解属性的值<br>
* 如果无指定的属性方法返回null
*
* @param <A> 注解类型
* @param <R> 注解类型值
* @param annotationEle {@link AnnotatedElement},可以是Class、Method、Field、Constructor、ReflectPermission
* @param propertyName 属性名,例如注解中定义了name()方法,则 此处传入name
* @return 注解对象
* @throws UtilException 调用注解中的方法时执行异常
* @since 5.8.9
*/
public static <A extends Annotation, R> R getAnnotationValue(AnnotatedElement annotationEle, Func1<A, R> propertyName) {
if (propertyName == null) {
return null;
} else {
final SerializedLambda lambda = LambdaUtil.resolve(propertyName);
final String instantiatedMethodType = lambda.getInstantiatedMethodType();
final Class<A> annotationClass = ClassUtil.loadClass(StrUtil.sub(instantiatedMethodType, 2, StrUtil.indexOf(instantiatedMethodType, ';')));
return getAnnotationValue(annotationEle, annotationClass, lambda.getImplMethodName());
}
}
/**
* 获取指定注解中所有属性值<br>
* 如果无指定的属性方法返回null
*
* @param annotationEle {@link AnnotatedElement},可以是Class、Method、Field、Constructor、ReflectPermission
* @param annotationType 注解类型
* @return 注解对象
* @throws UtilException 调用注解中的方法时执行异常
*/
public static Map<String, Object> getAnnotationValueMap(AnnotatedElement annotationEle, Class<? extends Annotation> annotationType) throws UtilException {
final Annotation annotation = getAnnotation(annotationEle, annotationType);
if (null == annotation) {
return null;
}
final Method[] methods = ReflectUtil.getMethods(annotationType, t -> {
if (ArrayUtil.isEmpty(t.getParameterTypes())) {
// 只读取无参方法
final String name = t.getName();
// 跳过自有的几个方法
return (false == "hashCode".equals(name)) //
&& (false == "toString".equals(name)) //
&& (false == "annotationType".equals(name));
}
return false;
});
final HashMap<String, Object> result = new HashMap<>(methods.length, 1);
for (Method method : methods) {
result.put(method.getName(), ReflectUtil.invoke(annotation, method));
}
return result;
}
/**
* 获取注解类的保留时间,可选值 SOURCE(源码时),CLASS(编译时),RUNTIME(运行时),默认为 CLASS
*
* @param annotationType 注解类
* @return 保留时间枚举
*/
public static RetentionPolicy getRetentionPolicy(Class<? extends Annotation> annotationType) {
final Retention retention = annotationType.getAnnotation(Retention.class);
if (null == retention) {
return RetentionPolicy.CLASS;
}
return retention.value();
}
/**
* 获取注解类可以用来修饰哪些程序元素,如 TYPE, METHOD, CONSTRUCTOR, FIELD, PARAMETER 等
*
* @param annotationType 注解类
* @return 注解修饰的程序元素数组
*/
public static ElementType[] getTargetType(Class<? extends Annotation> annotationType) {
final Target target = annotationType.getAnnotation(Target.class);
if (null == target) {
return new ElementType[]{ElementType.TYPE, //
ElementType.FIELD, //
ElementType.METHOD, //
ElementType.PARAMETER, //
ElementType.CONSTRUCTOR, //
ElementType.LOCAL_VARIABLE, //
ElementType.ANNOTATION_TYPE, //
ElementType.PACKAGE//
};
}
return target.value();
}
/**
* 是否会保存到 Javadoc 文档中
*
* @param annotationType 注解类
* @return 是否会保存到 Javadoc 文档中
*/
public static boolean isDocumented(Class<? extends Annotation> annotationType) {
return annotationType.isAnnotationPresent(Documented.class);
}
/**
* 是否可以被继承,默认为 false
*
* @param annotationType 注解类
* @return 是否会保存到 Javadoc 文档中
*/
public static boolean isInherited(Class<? extends Annotation> annotationType) {
return annotationType.isAnnotationPresent(Inherited.class);
}
/**
* 扫描注解类,以及注解类的{@link Class}层级结构中的注解,将返回除了{@link #META_ANNOTATIONS}中指定的JDK默认注解外,
* 按元注解对象与{@code annotationType}的距离和{@link Class#getAnnotations()}顺序排序的注解对象集合
*
* <p>比如:<br>
* 若{@code annotationType}为 A,且A存在元注解B,B又存在元注解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
*/
public static List<Annotation> scanMetaAnnotation(Class<? extends Annotation> annotationType) {
return AnnotationScanner.DIRECTLY_AND_META_ANNOTATION.getAnnotationsIfSupport(annotationType);
}
/**
* <p>扫描类以及类的{@link Class}层级结构中的注解,将返回除了{@link #META_ANNOTATIONS}中指定的JDK默认元注解外,
* 全部类/接口的{@link Class#getAnnotations()}方法返回的注解对象。<br>
* 层级结构将按广度优先递归,遵循规则如下:
* <ul>
* <li>同一层级中,优先处理父类,然后再处理父接口;</li>
* <li>同一个接口在不同层级出现,优先选择层级距离{@code targetClass}更近的接口;</li>
* <li>同一个接口在相同层级出现,优先选择其子类/子接口被先解析的那个;</li>
* </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
*/
public static List<Annotation> scanClass(Class<?> targetClass) {
return AnnotationScanner.TYPE_HIERARCHY.getAnnotationsIfSupport(targetClass);
}
/**
* <p>扫描方法,以及该方法所在类的{@link Class}层级结构中的具有相同方法签名的方法,
* 将返回除了{@link #META_ANNOTATIONS}中指定的JDK默认元注解外,
* 全部匹配方法上{@link Method#getAnnotations()}方法返回的注解对象。<br>
* 方法所在类的层级结构将按广度优先递归,遵循规则如下:
* <ul>
* <li>同一层级中,优先处理父类,然后再处理父接口;</li>
* <li>同一个接口在不同层级出现,优先选择层级距离{@code targetClass}更近的接口;</li>
* <li>同一个接口在相同层级出现,优先选择其子类/子接口被先解析的那个;</li>
* </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
*/
public static List<Annotation> scanMethod(Method method) {
return AnnotationScanner.TYPE_HIERARCHY.getAnnotationsIfSupport(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);
if (null == annotation) {
return null;
}
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}按顺序从上到下声明了A,B,C三个注解,且三注解存在元注解如下:
* <pre>
* A -&gt; M3
* B -&gt; M1 -&gt; M2 -&gt; M3
* C -&gt; M2 -&gt; M3
* </pre>
* 此时入参{@code annotationType}类型为{@code M2},则最终将优先返回基于根注解B合成的合成注解
*
* @param annotatedEle {@link AnnotatedElement},可以是Class、Method、Field、Constructor、ReflectPermission
* @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;
}
return AnnotationScanner.DIRECTLY
.getAnnotationsIfSupport(annotatedEle).stream()
.map(annotation -> getSynthesizedAnnotation(annotationType, annotation))
.filter(Objects::nonNull)
.findFirst()
.orElse(null);
}
/**
* 获取元素上所有指定注解
* <ul>
* <li>若元素是类,则递归解析全部父类和全部父接口上的注解;</li>
* <li>若元素是方法、属性或注解,则只解析其直接声明的注解;</li>
* </ul>
*
* <p>注解合成规则如下:
* 若{@code AnnotatedEle}按顺序从上到下声明了A,B,C三个注解,且三注解存在元注解如下:
* <pre>
* A -&gt; M1 -&gt; M2
* B -&gt; M3 -&gt; M1 -&gt; M2
* C -&gt; M2
* </pre>
* 此时入参{@code annotationType}类型为{@code M1},则最终将返回基于根注解A与根注解B合成的合成注解。
*
* @param annotatedEle {@link AnnotatedElement},可以是Class、Method、Field、Constructor、ReflectPermission
* @param annotationType 注解类
* @param <T> 注解类型
* @return 合成注解
* @see SynthesizedAggregateAnnotation
*/
public static <T extends Annotation> List<T> getAllSynthesizedAnnotations(AnnotatedElement annotatedEle, Class<T> annotationType) {
return AnnotationScanner.DIRECTLY
.getAnnotationsIfSupport(annotatedEle).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), AnnotationScanner.NOTHING);
}
/**
* 对指定注解对象及其元注解进行聚合
*
* @param annotations 注解对象
* @return 聚合注解
*/
public static SynthesizedAggregateAnnotation aggregatingFromAnnotationWithMeta(Annotation... annotations) {
return new GenericSynthesizedAggregateAnnotation(Arrays.asList(annotations), AnnotationScanner.DIRECTLY_AND_META_ANNOTATION);
}
/**
* 方法是否为注解属性方法。 <br>
* 方法无参数,且有返回值的方法认为是注解属性的方法。
*
* @param method 方法
*/
static boolean isAttributeMethod(Method method) {
return method.getParameterCount() == 0 && method.getReturnType() != void.class;
}
}
package cn.hutool.core.annotation;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
/**
* {@link AnnotationAttribute}的基本实现
*
* @author huangchengxing
*/
public class CacheableAnnotationAttribute implements AnnotationAttribute {
private boolean valueInvoked;
private Object value;
private boolean defaultValueInvoked;
private Object defaultValue;
private final Annotation annotation;
private final Method attribute;
public CacheableAnnotationAttribute(Annotation annotation, Method attribute) {
Assert.notNull(annotation, "annotation must not null");
Assert.notNull(attribute, "attribute must not null");
this.annotation = annotation;
this.attribute = attribute;
this.valueInvoked = false;
this.defaultValueInvoked = false;
}
@Override
public Annotation getAnnotation() {
return this.annotation;
}
@Override
public Method getAttribute() {
return this.attribute;
}
@Override
public Object getValue() {
if (!valueInvoked) {
valueInvoked = true;
value = ReflectUtil.invoke(annotation, attribute);
}
return value;
}
@Override
public boolean isValueEquivalentToDefaultValue() {
if (!defaultValueInvoked) {
defaultValue = attribute.getDefaultValue();
defaultValueInvoked = true;
}
return ObjectUtil.equals(getValue(), defaultValue);
}
}
package cn.hutool.core.annotation;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.multi.RowKeyTable;
import cn.hutool.core.map.multi.Table;
import cn.hutool.core.util.ObjectUtil;
import java.util.Collection;
import java.util.Comparator;
/**
* <p>带缓存功能的{@link SynthesizedAnnotationAttributeProcessor}实现,
* 构建时需要传入比较器,获取属性值时将根据比较器对合成注解进行排序,
* 然后选择具有所需属性的,排序最靠前的注解用于获取属性值
*
* <p>通过该处理器获取合成注解属性值时会出现隐式别名,
* 即子注解和元注解中同时存在类型和名称皆相同的属性时,元注解中属性总是会被该属性覆盖,
* 并且该覆盖关系并不会通过{@link Alias}或{@link Link}被传递到关联的属性中。
*
* @author huangchengxing
*/
public class CacheableSynthesizedAnnotationAttributeProcessor implements SynthesizedAnnotationAttributeProcessor {
private final Table<String, Class<?>, Object> valueCaches = new RowKeyTable<>();
private final Comparator<Hierarchical> annotationComparator;
/**
* 创建一个带缓存的注解值选择器
*
* @param annotationComparator 注解比较器,排序更靠前的注解将被优先用于获取值
*/
public CacheableSynthesizedAnnotationAttributeProcessor(Comparator<Hierarchical> annotationComparator) {
Assert.notNull(annotationComparator, "annotationComparator must not null");
this.annotationComparator = annotationComparator;
}
/**
* 创建一个带缓存的注解值选择器,
* 默认按{@link SynthesizedAnnotation#getVerticalDistance()}和{@link SynthesizedAnnotation#getHorizontalDistance()}排序,
* 越靠前的越优先被取值。
*/
public CacheableSynthesizedAnnotationAttributeProcessor() {
this(Hierarchical.DEFAULT_HIERARCHICAL_COMPARATOR);
}
@SuppressWarnings("unchecked")
@Override
public <T> T getAttributeValue(String attributeName, Class<T> attributeType, Collection<? extends SynthesizedAnnotation> synthesizedAnnotations) {
Object value = valueCaches.get(attributeName, attributeType);
// 此处理论上不可能出现缓存值为nul的情况
if (ObjectUtil.isNotNull(value)) {
return (T)value;
}
value = synthesizedAnnotations.stream()
.filter(ma -> ma.hasAttribute(attributeName, attributeType))
.min(annotationComparator)
.map(ma -> ma.getAttributeValue(attributeName))
.orElse(null);
valueCaches.put(attributeName, attributeType, value);
return (T)value;
}
}
package cn.hutool.core.annotation;
import cn.hutool.core.map.TableMap;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import java.util.function.Predicate;
/**
* 组合注解 对JDK的原生注解机制做一个增强,支持类似Spring的组合注解。<br>
* 核心实现使用了递归获取指定元素上的注解以及注解的注解,以实现复合注解的获取。
*
* @author Succy, Looly
* @since 4.0.9
**/
public class CombinationAnnotationElement implements AnnotatedElement, Serializable {
private static final long serialVersionUID = 1L;
/**
* 创建CombinationAnnotationElement
*
* @param element 需要解析注解的元素:可以是Class、Method、Field、Constructor、ReflectPermission
* @param predicate 过滤器,{@link Predicate#test(Object)}返回{@code true}保留,否则不保留
* @return CombinationAnnotationElement
* @since 5.8.0
*/
public static CombinationAnnotationElement of(AnnotatedElement element, Predicate<Annotation> predicate) {
return new CombinationAnnotationElement(element, predicate);
}
/**
* 注解类型与注解对象对应表
*/
private Map<Class<? extends Annotation>, Annotation> annotationMap;
/**
* 直接注解类型与注解对象对应表
*/
private Map<Class<? extends Annotation>, Annotation> declaredAnnotationMap;
/**
* 过滤器
*/
private final Predicate<Annotation> predicate;
/**
* 构造
*
* @param element 需要解析注解的元素:可以是Class、Method、Field、Constructor、ReflectPermission
*/
public CombinationAnnotationElement(AnnotatedElement element) {
this(element, null);
}
/**
* 构造
*
* @param element 需要解析注解的元素:可以是Class、Method、Field、Constructor、ReflectPermission
* @param predicate 过滤器,{@link Predicate#test(Object)}返回{@code true}保留,否则不保留
* @since 5.8.0
*/
public CombinationAnnotationElement(AnnotatedElement element, Predicate<Annotation> predicate) {
this.predicate = predicate;
init(element);
}
@Override
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
return annotationMap.containsKey(annotationClass);
}
@Override
@SuppressWarnings("unchecked")
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
Annotation annotation = annotationMap.get(annotationClass);
return (annotation == null) ? null : (T) annotation;
}
@Override
public Annotation[] getAnnotations() {
final Collection<Annotation> annotations = this.annotationMap.values();
return annotations.toArray(new Annotation[0]);
}
@Override
public Annotation[] getDeclaredAnnotations() {
final Collection<Annotation> annotations = this.declaredAnnotationMap.values();
return annotations.toArray(new Annotation[0]);
}
/**
* 初始化
*
* @param element 元素
*/
private void init(AnnotatedElement element) {
final Annotation[] declaredAnnotations = element.getDeclaredAnnotations();
this.declaredAnnotationMap = new TableMap<>();
parseDeclared(declaredAnnotations);
final Annotation[] annotations = element.getAnnotations();
if (Arrays.equals(declaredAnnotations, annotations)) {
this.annotationMap = this.declaredAnnotationMap;
} else {
this.annotationMap = new TableMap<>();
parse(annotations);
}
}
/**
* 进行递归解析注解,直到全部都是元注解为止
*
* @param annotations Class, Method, Field等
*/
private void parseDeclared(Annotation[] annotations) {
Class<? extends Annotation> annotationType;
// 直接注解
for (Annotation annotation : annotations) {
annotationType = annotation.annotationType();
// issue#I5FQGW@Gitee:跳过元注解和已经处理过的注解,防止递归调用
if (AnnotationUtil.isNotJdkMateAnnotation(annotationType)
&& false == declaredAnnotationMap.containsKey(annotationType)) {
if(test(annotation)){
declaredAnnotationMap.put(annotationType, annotation);
}
// 测试不通过的注解,不影响继续递归
parseDeclared(annotationType.getDeclaredAnnotations());
}
}
}
/**
* 进行递归解析注解,直到全部都是元注解为止
*
* @param annotations Class, Method, Field等
*/
private void parse(Annotation[] annotations) {
Class<? extends Annotation> annotationType;
for (Annotation annotation : annotations) {
annotationType = annotation.annotationType();
// issue#I5FQGW@Gitee:跳过元注解和已经处理过的注解,防止递归调用
if (AnnotationUtil.isNotJdkMateAnnotation(annotationType)
&& false == declaredAnnotationMap.containsKey(annotationType)) {
if(test(annotation)){
annotationMap.put(annotationType, annotation);
}
// 测试不通过的注解,不影响继续递归
parse(annotationType.getAnnotations());
}
}
}
/**
* 检查给定的注解是否符合过滤条件
*
* @param annotation 注解对象
* @return 是否符合条件
*/
private boolean test(Annotation annotation) {
return null == this.predicate || this.predicate.test(annotation);
}
}
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