最近在項目中使用了Ehcache緩存,使用方式是用Spring提供的 @Cacheable 注解的方式,這種方式簡單、快速、方便,推薦使用。
在使用的過程中,遇到了緩存不生效的情況,經過分析處理,總結如下:
1、Spring MVC 的Controller方法上使用 @Cacheable 注解,編譯運行都沒問題,但在調接口的時候發現接口沒走緩存,最簡單的判斷方式就是在本地啟服務,方法里打斷點,可以發現每次都能進入斷點,而如果走緩存的話,是不會進斷點的。
查了很多資料,一直沒解決,最終想到了Spring 使用@Cacheable添加緩存是基於面向切面的思想做的,實際上就是使用Java動態代理,創建實例的時候注入的是代理對象,在代理對象里調用實際的對象,這樣就可以在實際的方法執行前,處理一下緩存的邏輯:沒有找到緩存就往下執行,執行完把結果加入到緩存中;找到緩存則直接返回緩存的結果,不調用執行實際的方法。
然后去看了一下spring mvc的配置文件,添加上了 aop 相關的配置,重啟測試,果然緩存生效了,只有第一次進了斷點,后面都直接有結果,沒進斷點。
下圖是添加的配置:

2、一個方法A調同一個類里的另一個有緩存注解的方法B,這樣是不走緩存的。
原因就是上面說的,使用@Cacheable添加緩存實際上就是使用動態代理做的,在代理的方法前后做緩存的相應處理。這樣一來,單獨的去調方法B是有緩存的,但是如果調方法A,A里面再去調B方法,哪怕B方法配置了緩存,也是不會生效的。
解決方法:
a、不使用注解的方式,直接取 Ehcache 的 CacheManger 對象,把需要緩存的數據放到里面,類似於使用 Map,緩存的邏輯自己控制
b、把方法A和方法B放到兩個不同的類里面,例如:如果兩個方法都在service接口里,把方法B放到另一個service里面,這樣A方法里調B方法,就可以使用B方法的緩存
測試:

直接調用 test 方法,緩存是生效的;調用 hello 方法,test 方法的緩存不生效,每次都會執行一遍 test 方法里的代碼