Repeatable元注解的使用
在使用Mapstruct 实体类映射工具时,其中有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 – Java bean mappings, the easy way!