為了實作業務層緩存,定義了幾個注解:@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對于重複注解的實作其實就是個文法糖,内部實作還是注解嵌套的模式
但在開發體驗上确實比以前好多了!
寵辱不驚,看庭前花開花落;去留無意,望天上雲卷雲舒