前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >注解@Repeatable详解

注解@Repeatable详解

作者头像
孟君
发布2020-01-22 09:34:56
4.8K0
发布2020-01-22 09:34:56
举报

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

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

01

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

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

  • 定义注解ReviewRecord和ReviewRecords
代码语言:javascript
复制
package com.wangmengjun.tutorial.annotation;

public @interface ReviewRecord {

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

ReviewRecords注解如下:

代码语言:javascript
复制
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,代码示例如下:

代码语言:javascript
复制
  @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数组。

代码语言:javascript
复制
    ReviewRecords recordsAnno = ReviewRecordExample1.ctolass.getMethod("method1", String.class).getAnnotation(ReviewRecords.class);
    for(ReviewRecord recordAnno : recordsAnno.value()) {
      System.out.println(recordAnno);
    }

输出内容:

代码语言:javascript
复制
@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表明其可以重复使用。

代码语言:javascript
复制
package com.wangmengjun.tutorial.annotatiotn;

import java.lang.annotation.Repeatable;

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

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

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

代码语言:javascript
复制
  @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);
  }

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

代码语言:javascript
复制
  @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来获取即可。

代码语言:javascript
复制
    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注解可以让一个注解是否可以重复,意思更加明确
代码语言:javascript
复制
@Repeatable(ReviewRecords.class)
public @interface ReviewRecord {

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

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

代码语言:javascript
复制
  @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);
  }

这个其本质就是:

代码语言:javascript
复制
  @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注解后,一个和多个可以配套使用

可以采用原先的方式:

代码语言:javascript
复制
    @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);
  }

可以使用新的方式:

代码语言:javascript
复制
  @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);
  }

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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-12-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 孟君的编程札记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档