java8注解@Repeatable使用技巧
https://www.jianshu.com/p/4f65fae2510b
前言
@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)
//@Repeatable(Validates.class)
public @interface Validate {/*** 业务类型* @return*/String bizCode();/*** 订单类型* @return*/int orderType();}
我玩策略模式的时候喜欢用注解和spring结合做自动策略路由
上面的@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();}
注意这个聚合注解默认约束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();}
那么就可以在类上使用多个@Validate注解了。
回过头来看下@PropertySource和@PropertySources也是如此
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(PropertySources.class)
public @interface PropertySource /*** Container annotation that aggregates several {@link PropertySource} annotations.** <p>Can be used natively, declaring several nested {@link PropertySource} annotations.* Can also be used in conjunction with Java 8's support for <em>repeatable annotations</em>,* where {@link PropertySource} can simply be declared several times on the same* {@linkplain ElementType#TYPE type}, implicitly generating this container annotation.** @author Phillip Webb* @since 4.0* @see PropertySource*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PropertySources
从上面的注释中可以看到,spring在4.0支持了java8这个特性
原理
那么@Repeatable的原理是啥?
语法糖而已!
我们反编译下面代码
/*@Validates(value = {*/@Validate(bizCode = "fruit",orderType = 1)@Validate(bizCode = "fruit",orderType = 2)@Validate(bizCode = "vegetable",orderType = 2)
/*})*/
public class BizLogic2 {
}
发现反编译变成了
语法糖无疑了。
问题来了
那么再反编译下面代码试试
/*@Validates(value = {*/@Validate(bizCode = "fruit",orderType = 1)// @Validate(bizCode = "fruit",orderType = 2)//@Validate(bizCode = "vegetable",orderType = 2)
/*})*/
public class BizLogic2 {
}
生成
那这样就存在问题了,我以为加了@Repeatable之后@Validate都会生成被语法糖@Validates包裹。没想到它居然这么智能,只有一个@Validate注解的时候居然不转换。
所以使用多个@Validate的时候就会留坑,你需要兼容1个或多个的场景。
推荐方式
直接使用@Validates读取注解代码如下
Validates validates = AnnotationUtils.getAnnotation(BizLogic2.class,Validates.class);Arrays.stream(validates.value()).forEach(a->{System.out.println(a.bizCode());});
带兼容的逻辑如下
Validate validate = AnnotationUtils.getAnnotation(BizLogic.class,Validate.class);if(Objects.nonNull(validate)){System.out.println(validate.bizCode());}Validates validates = AnnotationUtils.getAnnotation(BizLogic2.class,Validates.class);Arrays.stream(validates.value()).forEach(a->{System.out.println(a.bizCode());});
如果你是自己写业务的,我觉得第一种方式更加方便。
但是如果你是开发中间件的,那么必须兼容,你永远不知道你的傻逼用户会干吗,哈哈。
还有一点需要注意,我的@Validate是被@Component元注解,当多个@Validate语法糖转换成@Validates之后,由于@Validates上没@Component,导致我的bean加载不到spring容器中去
java8注解@Repeatable使用技巧相关推荐
- java 元注解 @Repeatable
目录 一 笔记 二 自定义注解容器Persons 三 自定义的注解AnnotationTest08_Person ,即可重复使用的注解 四 通过反射机制获取重复注解的信息 一 笔记 元注解 @Repe ...
- Java注解 @Repeatable
** Repeatable使用场景: ** 当我们需要重复使用某个注解时,希望利用相同的注解来表现所有的形式时,我们可以借助@Repeatable注解. ** 实例 ** 在生活中一个人往往是具有多种 ...
- 自定义重复注解 @Repeatable 使用方式
注解基本概要: @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface FieldMap { ...
- java8 注解增强_Java8新增的重复注解功能示例
本文实例讲述了Java8新增的重复注解功能.分享给大家供大家参考,具体如下: 一 点睛 在Java 8以前,同一个程序元素前最多只能使用一个相同类型的Annotation:如果需要在同一个元素前使用多 ...
- Java注解——Repeatable
Repeatable使用场景: 在需要对同一种注解多次使用时,往往需要借助@Repeatable. 实例: 在生活中一个人往往是具有多种身份,如果我把每种身份当成一种注解该如何使用??? 先声明一个P ...
- JAVA注解 | 可重复元注解@Repeatable
目录 使用 @Repeatable 使用反射获取注解 约束 @Repeatable 是 JDK1.8 增加的元注解,用于声明当前注解是可重复的.如果有没有声明 @Repeatable,在同一个地方使用 ...
- springboot注解@Repeatable
@Repeatable 对同一种注解多次使用就会使用到@Repeatable @Documented @Retention(RetentionPolicy.RUNTIME) @Target(Eleme ...
- java8函数式编程 视频_快速掌握Java8 Stream函数式编程技巧
函数式编程优势"函数第一位",即函数可以出现在任何地方. 可以把函数作为参数传递给另一个函数,还可以将函数作为返回值. 让代码的逻辑更清晰更优雅. 减少了可变量(Immutable ...
- java8 注解: @FunctionalInterface (函数式接口)
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程. Java8提倡函数式编程,因而新增了一个函数式接口.函数式接口保证了函数式编程,同时也保证了能够兼容 ...
最新文章
- GPT-2仅是“反刍”知识,真正理解语言还要改弦更张
- 使用json-lib实现json to javabean
- Oracle 总复习
- XDP/eBPF — BPF
- Javassist 使用指南(一)
- C语言malloc动态分配内存分配失败怎么办?exit(OVERFLOW);(include <cstdlib>)
- Python 各种运行错误(如:SyntaxError :invalid syntax)
- 计算机网络怎么查看连接打印机驱动,涨姿势:手把手教你如何连接网络打印机...
- python减法怎么表示_python运算符号之一的减法怎么用,你真的学会用python的使用方法了嘛...
- EditText: 自定义EditText 触摸时无法获取焦点
- Android 中点击某个按钮实现 返回键 的功能
- 遍历一个数据去掉最后一个元素的样式
- String类得常用方法
- 项目中cxf和weblogic整合时报错的问题
- 二十一、 Memento 备忘录(行为型模式)
- Flash之swf文件的加密与破解
- 大国崛起:数据库领域的中国力量
- matlab如何把正弦转化为余弦公式,余弦和正切的换算关系(正弦余弦正切转换公式大全)...
- UVALive - 4487 HDU3234 UVA12232 【带权并查集】 非常好的一道题!!!
- Python翻译库 pygtrans 谷歌翻译
热门文章
- 《禅门锻炼说》十三篇自序
- office2010 启动man_OFFICE2010启动慢解决方案
- vant Ui 网址
- python:ai第五课:决策树的python实现调试,tree存储恢复,tree图绘制
- 工业互联网让“隔行”不再“如隔山”
- 自定义Dialog(QQ头像选择弹出的对话框)
- matlab 中matgray函数
- “内聚性”和“耦合性”
- 1052 Linked List Sorting (25 分)
- wordpress自动配图插件