在 JDK8 中增加了 Repeatable 注解,通过示例了解一下这个注解的功能。
package java.lang.annotation;
/**
* The annotation type {@code java.lang.annotation.Repeatable} is
* used to indicate that the annotation type whose declaration it
* (meta-)annotates is repeatable. The value of
* {@code @Repeatable} indicates the containing annotation
* type for the repeatable annotation type.
*
* @since 1.8
* @jls 9.6 Annotation Types
* @jls 9.7 Annotations
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Repeatable {
/**
* Indicates the containing annotation type for the
* repeatable annotation type.
* @return the containing annotation type
*/
Class extends Annotation> value();
}
The annotation type java.lang.annotation.Repeatable is used to indicate that the annotation type whose declaration it (meta-)annotates is repeatable. The value of @Repeatable indicates the containing annotation type for the repeatable annotation type.
@Repeatable 注解用于指示它注解声明的注解类型是可重复的。@Repeatable 的值用于指示一个注解类型,这个注解类型用来存放可重复的注解类型。
初次看这段文字时,觉得比较难以理解,经过思考,我认为 用户-角色场景可以通俗的解释 @Repeatable 注解。
一个系统中可以设定多个角色,每个角色我们称之为 Role,系统定义的角色如下:
一个用户(User)可以拥有其中的一个或者多个角色,用户拥有的角色列表我们称之为 Roles,假设有两个用户 User1、User2 ,他们的权限分别如下:
通过 @Repeatable 注解来实现以上功能
package org.learn.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(Roles.class)
public @interface Role {
String value() default "";
}
这里需要说明 @Repeatable(Roles.class)
,它指示在同一个类中 @Role
注解是可以重复使用的,重复的注解被存放至 @Roles
注解中。
package org.learn.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;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Roles {
Role[] value();
}
@Roles
注解是如何存放 @Role
注解的呢?它定义了 Role[] value();
用来存放可重复的注解。
这里提出一个问题,如果在同一个类中只有一个可重复的 @Role
注解,那这个值会被存入 @Roles
注解中吗?
package org.learn.annotation;
/**
* @author zhibo
* @date 2019/5/31 15:03
*/
@Role("system_admin")
public class User1 {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package org.learn.annotation;
/**
* @author zhibo
* @date 2019/5/31 15:03
*/
@Role("biz_admin")
@Role("custom")
public class User2 {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package org.learn.annotation;
/**
* @author zhibo
* @date 2019/5/31 15:00
*/
public class RepeatableDemo {
public static void main(String[] args) {
if(User1.class.isAnnotationPresent(Roles.class)){
Roles roles = User1.class.getAnnotation(Roles.class);
System.out.println("User1的角色如下:");
for (Role role : roles.value()){
System.out.println(role.value());
}
}
if(User2.class.isAnnotationPresent(Roles.class)){
Roles roles = User2.class.getAnnotation(Roles.class);
System.out.println("User2的角色如下:");
for (Role role : roles.value()){
System.out.println(role.value());
}
}
}
}
执行 main 方法,输出如下:
从执行结果中可以看到 User2 的角色列表,通过注解的值我们可以进行用户角色判定。
同时可以看到 User1 的角色是@Role("system_admin")
,但是 User1 的角色没有被输出,在加上一个 Role 的话,就可以输出角色了。由此可见,如果只声明了一个注解 Role(被 @Repeatable 声明的注解),那么注解值是不会被存放至 Roles 注解中的,测试类中不会存在 Roles 注解。
修改 User1 的代码,为其增加 @Role("custom")
角色:
package org.learn.annotation;
/**
* @author zhibo
* @date 2019/5/31 15:03
*/
@Role("system_admin")
@Role("custom")
public class User1 {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
再次执行 main 方法,结果如下:
与我们的预期一致,由此可见,在写代码时,不能用惯性思维去理解问题,面对不确定的问题,一定要通过代码进行验证。
文章内容仅代表个人观点,如有不正之处,欢迎批评指正,谢谢大家。