Repeatable元注解的使用
在使用Mapstruct 1实体类映射工具时,其中有Mapping注解可以在同一个方法上可以多次标记,那么这个操作是怎么实现的呢?
接下来我们来实现一个类似的注解,在类上加多个注解标记
基础类:
Value注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Value {
String value();
}
Parent类
@Value(value = "parent")
public class Parent {
}
Child类
@Value(value = "child")
public class Child extends Parent {
}
常规情况下我们使用的注解,都是如上代码所示,只会单次标记。
但是如果我们多次标记会出现什么问题呢?结果如下,在编译时就会提示我们重复使用相同的注解,建议使用Repeatable注解配合使用:
❓那么我们该如何调整才可以多次标记呢?
首先我们修改Value注解,在注解类上面添加Repeatable注解:
@Repeatable
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Value {
String value();
}
此时我们会发现有一个错误提示,必须要指定一个value属性,如下所示:
那么这个value属性是个什么样东西呢?我们来看下源码中的注释:
也就是说需要定义一个可以包含多次标记注解的注解类。
那么我们该怎么创建这个注解类呢?首先我们对边定义一个注解:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Values {
}
此时在idea开发工具中我们会发现,Values这个注解中会有一个关联错误提示,如下所示:
那么我们到关联的Value注解中看下,是一个什么样的错误?如下所示:
提示信息内容表明,在Values这个容器注解中,没有声明value这个方法!
那么我们声明一个跟Value注解中一样的方法,修改如下:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Values {
String value();
}
此时我们会发现,Value注解中还是会有错误提示,错误提示如下:
提示信息内容表示,我们声明一个的value方法要是一个数组类型的
我们将方法调整下,错误提示消失,也就表明我们这么做是正确的了,代码如下:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Values {
Value[] value();
}
那么我们写一个测试代码,来测试下,多次标记会是什么样子呢?
调整Child类,进行多次标记:
@Value(value = "child-1")
@Value(value = "child-2")
public class Child extends Parent {
}
AnnoMain测试类
public class AnnoMain {
public static void main(String[] args) {
Class<Child> clazz = Child.class;
if (clazz.isAnnotationPresent(Value.class)) {
Value valueAnnotation = clazz.getAnnotation(Value.class);
System.out.println("Data annotation present: " + valueAnnotation.value());
}
if (clazz.isAnnotationPresent(Values.class)) {
System.out.print("Datas annotation present: ");
Values dataAnnotation = clazz.getAnnotation(Values.class);
Value[] values = dataAnnotation.value();
for (Value value : values) {
System.out.print(value.value() + "\t");
}
}
}
}
执行结果如下:
我们会发现,这里在多次标记的情况下,会使用Values容器注解,会将多次标记的注解内容放到Values容器注解的数组中。
那么在这时我想大家也会有个疑问,在使用了Repeatable注解以及容器注解后是这样子,那么如果我只是单次标记,是否会使用容器注解呢?那么我们来调整下我们的Child类,只使用一次注解标记。
@Value(value = "child-1")
//@Value(value = "child-2")
public class Child extends Parent {
}
执行结果如下:
从结果上我们可以很明显的看出,如果使用单次标记就不会使用到容器注解,只有在多次标记的情况下才会使用到容器注解。
[ 1] mapstruct官网 mapstruct.org/