美文网首页
@Repeatable注解的用法

@Repeatable注解的用法

作者: overflow_e4e4 | 来源:发表于2021-04-06 16:52 被阅读0次

    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注解的用法

          本文链接:https://www.haomeiwen.com/subject/hdnskltx.html