专栏首页孟君的编程札记注解@Repeatable详解

注解@Repeatable详解

@Repeatable注解是JDK8加入的一个新特性。

本文算是对一个旧知识点的回顾和剖析。

01

未使用@Repeatable之前实现多个注解重复使用

在1.8之前,如果想多次使用一个注解进行描述,是如何完成的呢?举个例子,使用一个ReviewRecord注解来描述相关类、方法的Review信息。

  • 定义注解ReviewRecord和ReviewRecords
package com.wangmengjun.tutorial.annotation;

public @interface ReviewRecord {

  String name();
  String date();
  String comment() default "";;
}

ReviewRecords注解如下:

package com.wangmengjun.tutorial.annotation;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface ReviewRecords {

ton  ReviewRecord[] value();
}
  • 使用注解ReviewRecord和ReviewRecords

在使用的时候,需要先指定@ReviewRecords,然后指定多个ReviewRecord,代码示例如下:

  @ReviewRecords({
    @ReviewRecord(name="Eric", date="2019-12-19", comment="No comment"),
    @ReviewRecord(name="Joan", date="2019-12-29")
  })
  public void method1(String name) {
    System.out.println("Hello, " + name);
  }
  • 获取注解方法

获取某个方法ReviewRecord的注解信息,需要先获取ReviewRecords注解,然后通过ReviewRecords注解的value方法获取ReviewRecord数组。

    ReviewRecords recordsAnno = ReviewRecordExample1.ctolass.getMethod("method1", String.class).getAnnotation(ReviewRecords.class);
    for(ReviewRecord recordAnno : recordsAnno.value()) {
      System.out.println(recordAnno);
    }

输出内容:

@com.wangmengjun.tutorial.annotation.ReviewRecord(comment="No comment", name="Eric", date="2019-12-19")
@com.wangmengjun.tutorial.annotation.ReviewRecord(comment="", name="Joan", date="2019-12-29")

这种旧式写法,可以查看javax.annotation.Resource和javax.annotation.Resources的示例,如:

02

使用@Repeatable后实现多个注解重复使用

修改ReviewResource注解,增加@Repeatable表明其可以重复使用。

package com.wangmengjun.tutorial.annotatiotn;

import java.lang.annotation.Repeatable;

@Repeatable(ReviewRecords.class)
public @interface ReviewRecord {

  String name();
  String date();
  String comment() default "";;
}

使用的时候,不需要指定是ReviewRecords,如:

  @ReviewRecord(name="Eric", date="2019-12-19", comment="No comment")
  @ReviewRecord(name="Joan", date="2019-12-29")
  public void method3(String message) {
    System.out.println(message);
  }

这种方法本质上等同于如下代码:

  @ReviewRecords({
    @ReviewRecord(name="Eric", date="2019-12-19", comment="No comment"),
    @ReviewRecord(name="Joan", date="2019-12-29")
  })
  public void method3(String name) {
    System.out.println("Hello, " + name);
  }

这个我们可以通过javap查看编译后的信息获取:

如:javap -v ReviewRecordExample1.class

  • 获取注解方法

获取注解可以通过getAnnotationsByType来获取即可。

    ReviewRecord[] recordAnnoArr = ReviewRecordExample1.class.getMethod("method3", String.class).getAnnotationsByType(ReviewRecord.class);
    for(ReviewRecord recordAnno : recordAnnoArr) {
      System.out.println(recordAnno);
    }

现在很多地方都使用@Repeatable注解了,如sping-boot-test中的MockBean、MockBeans以及SpyBean和SpyBeans等,如:

03

小结

通过上述的示例,相信大家对@Repeatable注解的使用有了一定的了解。接下来,我们来做一个小结:

  • 使用@Repeatable注解可以让一个注解是否可以重复,意思更加明确
@Repeatable(ReviewRecords.class)
public @interface ReviewRecord {

  String name();
  String date();
  String comment() default "";;
}
  • 使用@Repeatable注解后,其本质是对原先语法的增强

使用@Repeatable注解后,可以支持如下场景:

  @ReviewRecord(name="Eric", date="2019-12-19", comment="No comment")
  @ReviewRecord(name="Joan", date="2019-12-29")
  public void method1(String name) {
    System.out.println("Hello, " + name);
  }

这个其本质就是:

  @ReviewRecords({
    @ReviewRecord(name="Eric", date="2019-12-19", comment="No comment"),
    @ReviewRecord(name="Joan", date="2019-12-29")
  })
  public void method3(String name) {
    System.out.println("Hello, " + name);
  }
  • 使用@Repeatable注解后,一个和多个可以配套使用

可以采用原先的方式:

    @ReviewRecords({
        @ReviewRecord(name="Eric", date="2019-12-19", comment="No comment"),
        @ReviewRecord(name="Joan", date="2019-12-29")
      })
      public void method1(String name) {
        System.out.println("Hello, " + name);
      }
  
  
  @ReviewRecords({@ReviewRecord(name="Eric", date="2019-12-19", comment="No comment")})
  public void method2(String message) {
    System.out.println(message);
  }

可以使用新的方式:

  @ReviewRecord(name="Eric", date="2019-12-19", comment="No comment")
  @ReviewRecord(name="Joan", date="2019-12-29")
  public void method1(String name) {
    System.out.println("Hello, " + name);
  }
  
  //这种方式原来也支持,但是和多个重复注解的配置有配置上不同
  //但是,使用@Repeatable引入后,一个和多个可以匹配上
  @ReviewRecord(name="Eric", date="2019-12-19", comment="No comment")
  public void method2(String message) {
    System.out.println(message);
  }

两种方式,大家都可以使用。本文比较偏向于第二种,你们喜欢哪一个?

本文分享自微信公众号 - 孟君的编程札记(gh_0f0f5e0ae1de),作者:孟君

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-12-29

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 一步步完成jsRender + Spring MVC + Nginx前后端分离示例

    本篇博文的目标是使用前端页面渲染插件jsRender做前后端分离,后端采用Spring MVC给出REST API,并结合Nginx完成配置。

    孟君
  • 设计模式之结构模式集合

    结构模式描述如何将类或者对象结合在一起形成更大的结构。再来回顾一下各个结构模式的意图和结构。

    孟君
  • 状态模式解析

    状态在我们的生活中无处不在。比如,听音乐的时候,我们可以选择不同的播放状态,可以是顺序播放、可以是单曲播放、也可以随机播放等;又如:线上购物后,订单从提交到完成...

    孟君
  • JSP---JavaBean的使用-jsp:useBean标签相关

    JavaBean的scope属性决定的Bean的范围,默认为page范围。 当声明了一个Bean并将它放到某个范畴之后,在同一个范围内再次使用<jsp:us...

    谙忆
  • PL/SQL Developer中文版下载以及使用图解(绿色版)

    下载地址:http://pan.baidu.com/s/1eQCTmkM 1、运行plsqldev.exe程序; 2、设置Oracle主目录名/OCI库地址,如...

    Java中文社群-磊哥
  • 用Word排版伪代码out了,推荐这个工具

    多少次你看到别人的的伪代码排版如此完美而惊艳,心中不免好奇,怎么设计的?今天,和大家一起学习一款流行的排版利器:CTeX

    double
  • java之struts2之数据检验

    1.使用struts2时,有时候需要对数据进行相关的验证。如果对数据的要求比较严格,或对安全性要求比较高时,前端 js 验证还不够,

    Vincent-yuan
  • .NET Migration工具

    Migration是一种分布环境下的数据库同步工具,出现在Ruby on Rail框架里,MigratorDotNet是一个.NET类似于Ruby on Rai...

    张善友
  • SpringBoot2.x基础篇:谈谈SpringBoot内提供的这几种配置绑定

    SpringBoot在不断地版本迭代中陆续提供了不同的配置参数绑定的方式,我们可以单独获取一个配置参数也可以将一系列的配置映射绑定到JavaBean的属性字段,...

    恒宇少年
  • ASP.NET Core的路由[2]:路由系统的核心对象——Router

    ASP.NET Core应用中的路由机制实现在RouterMiddleware中间件中,它的目的在于通过路由解析为请求找到一个匹配的处理器,同时将请求携带的数据...

    蒋金楠

扫码关注云+社区

领取腾讯云代金券