我是靠谱客的博主 纯情鼠标,最近开发中收集的这篇文章主要介绍@Repeatable注解学习,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

前言

@Repeatable注解是java8为了解决同一个注解不能重复在同一类/方法/属性上使用的问题。

举一个比较贴近开发的例子,在spring/springboot我们引入资源文件可以使用注解@PropertySource

@PropertySource("classpath:sso.properties")
public class Application {
}

那要引入多个资源文件怎么办,没事,我把PropertySource中的value设置成String[]数组就行了

public @interface PropertySource {
...
String[] value();
}

那么就能这么用

@PropertySource({"classpath:sso.properties","classpath:dubbo.properties","classpath:systemInfo.properties"})
public class Application {
}

就spring引入配置文件来讲,肯定是没事问题的。但是如果注解中2个值存在依赖关系,那么这样就不行了。比如下面这个

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Validate {
/**
* 业务类型
* @return
*/
String bizCode();
/**
* 订单类型
* @return
*/
int orderType();
}

上面的@validate注解,bizcode和orderType是一对一的关系,我希望可以添加如下的注解

@Validate(bizCode = "fruit",orderType = 1)
@Validate(bizCode = "fruit",orderType = 2)
@Validate(bizCode = "vegetable",orderType = 2)
public class BizLogic2 {
}

很抱歉在java8之前,这种方式不行,不过你可以这么做,新建一个如下的注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
public @interface Validates {
Validate[] value();
}

然后对应代码修改如下

@Validates(value = {
@Validate(bizCode = "fruit",orderType = 1)
@Validate(bizCode = "fruit",orderType = 2)
@Validate(bizCode = "vegetable",orderType = 2)
})
public class BizLogic2 {
}

在java8的@Repeatable出来之后,我们在不改动@Validates的情况下,对@Validate进行修改,增加
@Repeatable(Validates.class)

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Repeatable(Validates.class)
public @interface Validate {
/**
* 业务类型
* @return
*/
String bizCode();
/**
* 订单类型
* @return
*/
int orderType();
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
public @interface Validates {
Validate[] value();
}

注意,一旦使用Repeatable注解指定了注解Validates,那么这个聚合注解默认约束value来存储子注解,用其他的名字代替value均会编译报错

那么就可以在类上使用多个@Validate注解了。

@Validate(bizCode = "fruit",orderType = 1)
@Validate(bizCode = "fruit",orderType = 2)
@Validate(bizCode = "vegetable",orderType = 2)
public class BizLogic2 {
}

还有一点需要注意,我的@Validate是被@Component元注解标注,当多个@Validate语法糖转换成@Validates之后,由于@Validates上没@Component,导致我的bean加载不到spring容器中去

原理

那么@Repeatable的原理是啥?
其实就是语法糖

对于下面的注解

@Repeatable(Persons.class)
public @interface Person {
String role() default "";
String name() default "";
}
public @interface Persons {
Person[] value();
}

我们给下面这个类加上注解,重点关注这个类,打开这个编译后的类(即这个java文件对应的class文件)

@Person(role = "警察",name = "小花")
@Person(role = "小偷",name = "笑话")
public class AnnotationTest {
}

我们得到下面的代码

@Persons({@Person(
role = "警察",
name = "小花"
), @Person(
role = "小偷",
name = "笑话"
)})
public class AnnotationTest {
public AnnotationTest() {
}
}

从这里可以看出的确就是语法糖。

问题来了
我们打开下面这个编译后的类

@Person(role = "警察",name = "小花")
public class AnnotationTest {
}

得到的结果是这样

@Person(
role = "警察",
name = "小花"
)
public class AnnotationTest {
public AnnotationTest() {
}
}

那这样就存在问题了,我以为加了@Repeatable之后@Validate都会生成被语法糖@Validates包裹。没想到它居然这么智能,只有一个@Validate注解的时候居然不转换。
所以使用多个@Validate的时候就会留坑,你需要兼容1个或多个的场景。

最后

以上就是纯情鼠标为你收集整理的@Repeatable注解学习的全部内容,希望文章能够帮你解决@Repeatable注解学习所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(47)

评论列表共有 0 条评论

立即
投稿
返回
顶部