天天看點

ehcache模糊批量移除緩存

衆所周知,encache是現在最流行的java開源緩存架構,配置簡單,結構清晰,功能強大。通過注解<code>@Cacheable</code>可以快速添加方法結果到緩存。通過<code>@CacheEvict</code>可以快速清除掉指定的緩存。

但由于<code>@CacheEvict</code>注解使用的是key-value的,不支援模糊删除,就會遇到問題。當我用<code>@Cacheable</code>配合Spring EL表達式添加了同一方法的多個緩存比如:

上述代碼是分頁擷取任務資訊。用EL表達式擷取到參數中的page,并作為緩存的key,使用<code>@Cacheable</code>添加到ehcache的緩存中。此時,在緩存中就會出現<code>listOfTask_1</code>, <code>listOfTask_2</code>, <code>listOfTask_3</code>這種類型的key。

當添加、删除任務時,清單就會發生改變。這時候,就需要把<code>listOfTask_*</code>相關的緩存全部去掉。而這時,我不知道緩存中到底緩存了多少和<code>listOfTask_*</code>相關的内容,不可能調用<code>@CacheEvict</code>挨個删除。

既然ehcache本身無法支援,那就隻能靠我們自己實作了。

考慮到使用的注解添加的緩存,那麼移除緩存也使用注解處理,可以保持開發的一緻性。注解對開發者來說也很友好。那麼我們就考慮使用自定義注解來來模糊批量移除緩存。

首先,定義注解<code>CacheRemove</code>:

其中,value 同 ehcache 一樣,用于定義要操作的緩存名。key 是一個數組,用于存放多種緩存 key 的正規表達式。起名 <code>CacheRemove</code> 清晰易懂,也不與 ehcache 本身的注解沖突。注解的定義到此為止。接下來,就需要處理注解了,由于使用的 spring 架構,很自然的,就會想到用 AOP 來做注解的具體實作。

注解的目的是批量模糊移除緩存。需考慮如下兩個問題:

用什麼方式模糊比對

怎麼批量删除key

我給出的處理方式,也是我認為最簡單的處理方式是:

用什麼方式模糊比對 —— <code>CacheRemove</code>中的key傳正則,可以傳多個,使用正則比對

怎麼批量删除key —— 循環所有的key,找到比對正則的就删除

首先定義類名<code>CacheRemoveAspect</code>:

在切面中定義切點,使用<code>execution(* *.*(..) &amp;&amp; @annotation(com.example.CacheRemove))</code>表示所有帶注解類<code>CacheRemove</code>都執行,<code>@annotation</code>中的值是注解的全限定名。

切點定義完畢,下面的重頭戲就是切面的具體實作了。一般來說,緩存會在增删改的方法執行完後才要移除。是以使用<code>@AfterReturning()</code>來實作。在具體實作中需要做以下幾件事:

攔截方法上的注解

判斷注解是不是<code>CacheRemove</code>

由于注解傳入的 key 是個數組,循環處理每個key

在循環中編制每個 key 為 pattern, 并循環所有的緩存,移除比對上的緩存

具體實作如下:

以上,為 ehcache 模糊批量移除緩存的具體實作。其中 BusinessCacheUtils 為自己封裝的 ehcache 工具類。主要實作擷取緩存池,擷取緩存,移除緩存,添加緩存,檢視所有緩存等正常功能。代碼如下:

至此,整個ehcache 模糊批量移除緩存的功能就實作了。

整個過程思路簡單,用到了一些 AOP 的知識就完成了需要的功能。但具體的移除部分代碼可考慮進行優化。通過一次緩存的全部循環,就把需要移除的緩存都移除幹淨,而不是想現在這樣有幾個key,就全緩存周遊幾次。具體實作留給讀者自行完成。希望對各位有所幫助。