jdk8环境下,添加重复注解的美好体验
为了实现业务层缓存,定义了几个注解:@Cache.able、@Cache.put、@Cache.del
分别实现对业务方法的 缓存检测、缓存插入 和 缓存清除。
public @interface Cache { /**
* 缓存检测
* @author netwild
*/
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD })
public static @interface able{ String cache() default ""; String key() default ""; } /**
* 缓存插入
* @author netwild
*/
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD })
public static @interface put{ String cache() default ""; String key() default ""; } /**
* 缓存清除
* @author netwild
*/
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD })
public static @interface del{ String cache() default ""; String key() default "" } }
对一个业务方法来说,前两个注解没必要添加多个,但 缓存清除 的注解在有些时候需要多次引用,比如:
@Override
@Cache.del(key="#(id)")
@Cache.del(key="ItemMap")
public boolean deleteById(String id) {
return super.deleteById(id);
}
以上的业务方法很简单,就是根据ID删除指定的Model
但对于缓存来说,不仅要清除相应Key值的单条数据,还要清除包含这个Model的集合数据
所以就需要为这个业务方法添加两个 @Cache.del 注解来实现上面的需求
但此时会发现IDE的错误提示:
Duplicate annotation of non-repeatable type @Cache.del.
Only annotation types marked @Repeatable can be used multiple times at one target.
我的环境是JDK8,支持重复注解就是JDK8的一个新特性,下面就来试验一下
按照提示,给 @Cache.del 增加 @Repeatable 子注解,同时创建一个包含 @Cache.del 的容器注解:
/**
* 缓存清除
* @author netwild
*/
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD })
@Repeatable(Cache.dels.class) //支持重复注解,同时指定容器注解
public static @interface del{ String cache() default ""; String key() default "" } /**
* 缓存清除容器
* @author netwild
*/
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD })
public static @interface dels{ Cache.del[] value(); } //容器内定义指定类型的数组
代码中的红色部分是需要特殊注意的
其中对于原有的 @Cache.del 增加了 @Repeatable 子注解,说明该注解可以重复使用,同时指定了重复注解的 数据保存容器
之后增加的 @Cache.dels 就是容器注解,只在获取注解数据时使用,平时这个注解属于隐身状态
上面的修改完成之后,会发现之前在业务方法上添加的重复注解不再提示错误了,OK
最后看看如何获取重复注解的数据:
Annotation[] annos = method.getAnnotations();
if(annos.length > 0){
Arrays.stream(annos).forEach(anno -> {
if(anno instanceof Cache.del){ //单条清除注解
Cache.del temp = (Cache.del)anno;
String cacheName = buildCacheName(temp.cache());
String cacheKey = buildCacheKey(temp.key());
//具体处理逻辑
}else if(anno instanceof Cache.dels){ //多条清除注解
Cache.dels dels = (Cache.dels)anno;
Cache.del[] delarr = dels.value();
Arrays.stream(delarr).forEach(temp -> {
String cacheName = temp.cache();
String cacheKey = temp.key();
//具体处理逻辑
}
}
});
}
在遍历注解时,需要同时判断单条注解和重复注解两种情况
如果业务方法只添加了一个@Cache.del注解,那么不会执行注解容器;否则需要从容器中获得重复注解的数据
看到最后,我们才发现,JDK8对于重复注解的实现其实就是个语法糖,内部实现还是注解嵌套的模式
但在开发体验上确实比以前好多了!
jdk8环境下,添加重复注解的美好体验的更多相关文章
- JDK8新特性之重复注解
什么是重复注解 下面是JDK8中的重复注解(java.lang.annotation.Repeatable)定义的源码. @Documented @Retention(RetentionPolicy. ...
- jdk8系列二、jdk8方法引用、重复注解、更好的类型推断、新增注解
一.方法引用 方法引用使得开发者可以直接引用现存的方法.Java类的构造方法或者实例对象.方法引用和Lambda表达式配合使用,使得java类的构造方法看起来紧凑而简洁,没有很多复杂的模板代码. 方法 ...
- 如何在SAP云平台的Cloud Foundry环境下添加新的Service(服务)
我想在SAP云平台的Cloud Foundry环境下使用MongoDB的服务,但是我在Service Marketplace上找不到这个服务. cf marketplace返回的结果也没有. 解决方案 ...
- Linux环境下添加ftp账号步骤
(1)远程登录Linux服务器所用的工具,免费开源,可以从网站上很容易就下载到. (2)打开putty,输入服务器IP,进入后按提示进入用户名和密码输入超级管理员 root,然后系统让输入密码,注意此 ...
- IDEA环境下SSM整合------注解开发
根据前一篇文章的步骤,目前项目进度应该是:核心过滤器配置完成.DispatcherServlet和ContextLoader配置完成.数据库dataSource配置完成.视图解析器配置完成.Mappe ...
- LAMP 环境下添加多个虚拟主机(网站)
Ubuntu系统 #在/var/www目录下新建两个文件夹bbs和oa,执行完以上命令后,/var/www目录下有bbs.oa三个文件夹,名称与二级域名对应,分别存放三个系统的php文件,这样便于日后 ...
- As环境下添加android support library依赖库
2015年的google大会上,google发布了新的Android Support Design库的新组件之一,以此来全面支持Material Design 设计风格的UI效果,为了可以使用这些新颖 ...
- 在MyEclipse环境下添加MySql数据库
首先最好在添加的时候,确保你的数据库处于打开状态:其次,要按照jdbc:mysql://[host:port],[host:port].../[database]把url写对:然后,需要添加mysql ...
- IIS8.5 的环境下添加配置WCF服务!!!!!
添加步骤: 1.打开iis8.5,先部署wcf服务. 2.首先添加MIME类型 扩展名:“.svc” MIME类型:“application/octet-stream” 3.添加 处理程序映射 请求路 ...
随机推荐
- 我在项目中运用 IOC(依赖注入)--实战篇
上一篇<我在项目中运用 IOC(依赖注入)--入门篇>只是简单的使用 IOC.实际项目使用 IOC 的情景复杂多了,比如说,构造函数有多个参数,有多个类继承同一个接口... Unity都有 ...
- httpServletRequest中的流只能读取一次的原因
首先,我们复习一下InputStream read方法的基础知识, java InputStream read方法内部有一个,postion,标志当前流读取到的位置,每读取一次,位置就会移动一次,如果 ...
- Es创建索引、设置和修改Mapping
Http接口操作示例如下: 1.创建索引: 2.删除索引: 3.创建mapping: 4.查看mapping:
- 撩课-Web大前端每天5道面试题-Day19
1.实现一个函数clone,可以对JavaScript中的5种主要的数据类型(包括Number.String.Object.Array.Boolean)进行值复制 考察点1:对于基本数据类型和引用数据 ...
- Java Swing实战(一)JFrame和JTabbedPane容器
概述: 项目是一个桌面程序,涉及标签和按钮组件.布局管理器组件.面板组件.列表框和下拉框组件等组件,以及Swing事件处理机制. 下面先从最基础的界面开始. /** * @author: lishua ...
- golang chan 发送接收测试数据
测试代码: package main import ( "fmt" "time" ) const ( num = 10000000 / ...
- CodeForces765C
C. Table Tennis Game 2 time limit per test:2 seconds memory limit per test:512 megabytes input:stand ...
- iphone设置fiddler代理测试
iPhone上配置fiddler为代理方法: 打开IPhone, 找到你的网络连接,打开HTTP代理,输入Fiddler所在机器的IP地址(比如:192.168.1.104) 以及Fiddler的端口 ...
- mybatis作用、基本使用、小结
1. MyBatis 1.1. 作用 MyBatis是持久层框架,它是支持JDBC的!简化了持久层开发! 使用MyBatis时,只需要通过接口指定数据操作的抽象方法,然后配置与之关联的SQL语句,即可 ...
- python之定义函数
1.定义函数和参数检查 通过def语句定义一个函数,自己定义的函数,当参数个数不对时,python解释器可以抛出TypeError,但是当参数类型不对时,无法抛出TypeError,为此可以通过isi ...