爲了實現業務層緩存,定義了幾個註解:@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 "" } }
對一個業務方法來講,前兩個註解不必添加多個,但 緩存清除 的註解在有些時候須要屢次引用,好比:ide
@Override @Cache.del(key="#(id)") @Cache.del(key="ItemMap") public boolean deleteById(String id) { return super.deleteById(id); }
以上的業務方法很簡單,就是根據ID刪除指定的Modelui
但對於緩存來講,不只要清除相應Key值的單條數據,還要清除包含這個Model的集合數據spa
因此就須要爲這個業務方法添加兩個 @Cache.del 註解來實現上面的需求code
但此時會發現IDE的錯誤提示:blog
Duplicate annotation of non-repeatable type @Cache.del.
Only annotation types marked @Repeatable can be used multiple times at one target.
個人環境是JDK8,支持重複註解就是JDK8的一個新特性,下面就來試驗一下ip
按照提示,給 @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(); } //容器內定義指定類型的數組
代碼中的紅色部分是須要特殊注意的get
其中對於原有的 @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對於重複註解的實現其實就是個語法糖,內部實現仍是註解嵌套的模式
但在開發體驗上確實比之前好多了!