概述
前言
@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注解学习所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复