@Repeatable注解的用法

1. Repeatable注解的定义

java8以后支持在同一个地方(某个方法或者某个类等)加上相同的注解,前提是要使用@Repeatable注解,但是在用之前必须知道如何定义一个自定义注解:
自定义注解示例:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@Repeatable(ActionUnlockChecks.class)
public @interface ActionUnlockCheck {
    int actionType();
}
  • @Retention
    @Retention注解有一个属性value,是RetentionPolicy枚举类型Rentention搭配RententionPolicy使用。RetentionPolicy有3个值:CLASS RUNTIME SOURCE
    按生命周期来划分可分为3类:
    RetentionPolicy.SOURCE:注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃;
    RetentionPolicy.CLASS:注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期;
    RetentionPolicy.RUNTIME:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在;
    一般要用反射获得注解就要使用RUNTIME

  • @Target
    注解的作用域,属性value是数组,可以如示例所示填多个作用域,常用的有:TYPE,METHOD,PARAMETER,CONSTRUCTOR

  • @Repeatable
    属性value的类型是Class类型,这里创建了一个另一个自定义注解,后面称之为父注解,之前的称之为子注解,示例代码如下:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface ActionUnlockChecks {
    ActionUnlockCheck[]  value();
}

父注解必须有以下特征:
1:作用域必须大于等于子注解
2:父注解的周期要比子注解的周期要小或相同(注意:SOURCE(源码) < CLASS (字节码) < RUNTIME(运行))
3:父注解的value的类型是子注解类型的数组

2. Repeatable注解与反射

java反射是可以得到作用域RUNTIME的注解的,通过比如java.lang.Class#getAnnotation方法:

        ActionUnlockCheck annotation = joinPoint.getTarget().getClass().getAnnotation(ActionUnlockCheck.class);

但是这就有疑问了:既然注解是可重复的,那这个方法的返回值应该是数组而不是单个?
于是略加研究后发现,当我重复定义了@ActionUnlockCheck时,其实经过编译后,字节码class内部是这样的:

@ActionUnlockChecks({@ActionUnlockCheck(
    actionType = 114
), @ActionUnlockCheck(
    actionType = 113
)})

也就是说多个子注解其实会被转换成一个父注解。

你可能感兴趣的:(@Repeatable注解的用法)