SpringBoot系列緩存註解@Cacheable @CacheEvit @CachePut使用姿式介紹
Spring在3.1版本,就提供了一條基於註解的緩存策略,實際使用起來仍是很絲滑的,本文將針對幾個經常使用的註解進行簡單的介紹說明,有須要的小夥伴能夠嘗試一下java
本文主要知識點:git
<!-- more -->github
本項目藉助SpringBoot 2.2.1.RELEASE
+ maven 3.5.3
+ IDEA
+ redis5.0
進行開發web
開一個web服務用於測試redis
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> </dependencies>
全程使用默認配置,redis本機,端口6379,無密碼spring
@Cacheable
這個註解用於修飾方法or類,當咱們訪問它修飾的方法時,優先從緩存中獲取,若緩存中存在,則直接獲取緩存的值;緩存不存在時,執行方法,並將結果寫入緩存緩存
這個註解,有兩個比較核心的設置bash
/** * 與 cacheNames 效果等價 */ @AliasFor("cacheNames") String[] value() default {}; @AliasFor("value") String[] cacheNames() default {}; /** * 緩存key */ String key() default "";
cacheNames能夠理解爲緩存key的前綴,能夠爲組件緩存的key變量;當key不設置時,使用方法參數來初始化,注意key爲SpEL表達式,所以若是要寫字符串時,用單引號括起來app
一個簡單的使用姿式less
/** * 首先從緩存中查,查到以後,直接返回緩存數據;不然執行方法,並將結果緩存 * <p> * redisKey: cacheNames + key 組合而成 --> 支持SpEL * redisValue: 返回結果 * * @param name * @return */ @Cacheable(cacheNames = "say", key = "'p_'+ #name") public String sayHello(String name) { return "hello+" + name + "-->" + UUID.randomUUID().toString(); }
如咱們傳參爲 yihuihui, 那麼緩存key爲 say::p_yihuihui
除了上面三個配置值以外,查看@Cacheable
註解源碼的童鞋能夠看到還有condition
設置,這個表示當它設置的條件達成時,才寫入緩存
/** * 知足condition條件的才寫入緩存 * * @param age * @return */ @Cacheable(cacheNames = "condition", key = "#age", condition = "#age % 2 == 0") public String setByCondition(int age) { return "condition:" + age + "-->" + UUID.randomUUID().toString(); }
上面這個case中,age爲偶數的時候,才走緩存;不然不寫緩存
接下來是unless
參數,從名字上能夠看出它表示不知足條件時才寫入緩存
/** * unless, 不知足條件才寫入緩存 * * @param age * @return */ @Cacheable(cacheNames = "unless", key = "#age", unless = "#age % 2 == 0") public String setUnless(int age) { return "unless:" + age + "-->" + UUID.randomUUID().toString(); }
無論緩存有沒有,都將方法的返回結果寫入緩存;適用於緩存更新
/** * 無論緩存有沒有,都寫入緩存 * * @param age * @return */ @CachePut(cacheNames = "t4", key = "#age") public String cachePut(int age) { return "t4:" + age + "-->" + UUID.randomUUID().toString(); }
這個就是咱們理解的刪除緩存
/** * 失效緩存 * * @param name * @return */ @CacheEvict(cacheNames = "say", key = "'p_'+ #name") public String evict(String name) { return "evict+" + name + "-->" + UUID.randomUUID().toString(); }
在實際的工做中,常常會遇到一個數據變更,更新多個緩存的場景,對於這個場景,能夠經過@Caching
來實現
/** * caching實現組合,添加緩存,並失效其餘的緩存 * * @param age * @return */ @Caching(cacheable = @Cacheable(cacheNames = "caching", key = "#age"), evict = @CacheEvict(cacheNames = "t4", key = "#age")) public String caching(int age) { return "caching: " + age + "-->" + UUID.randomUUID().toString(); }
上面這個就是組合操做
caching::age
緩存取數據,不存在時執行方法並寫入緩存;t4::age
上面的幾個case,都是正常的場景,當方法拋出異常時,這個緩存表現會怎樣?
/** * 用於測試異常時,是否會寫入緩存 * * @param age * @return */ @Cacheable(cacheNames = "exception", key = "#age") @Cacheable(cacheNames = "say", key = "'p_yihuihui'") public int exception(int age) { return 10 / age; }
根據實測結果,當age==0
時,上面兩個緩存都不會成功
接下來驗證下緩存註解與上面描述的是否一致
@RestController public class IndexRest { @Autowired private BasicDemo helloService; @GetMapping(path = {"", "/"}) public String hello(String name) { return helloService.sayHello(name); } }
上面這個主要是驗證@Cacheable
註解,若緩存不命中,每次返回的結果應該都不同,然而實際訪問時,會發現返回的都是相同的
curl http://localhost:8080/?name=yihuihui
失效緩存
@GetMapping(path = "evict") public String evict(String name) { return helloService.evict(String.valueOf(name)); }
失效緩存,須要和上面的case配合起來使用
curl http://localhost:8080/evict?name=yihuihui curl http://localhost:8080/?name=yihuihui
剩下其餘的相關測試類就比較好理解了,一併貼出對應的代碼
@GetMapping(path = "condition") public String t1(int age) { return helloService.setByCondition(age); } @GetMapping(path = "unless") public String t2(int age) { return helloService.setUnless(age); } @GetMapping(path = "exception") public String exception(int age) { try { return String.valueOf(helloService.exception(age)); } catch (Exception e) { return e.getMessage(); } } @GetMapping(path = "cachePut") public String cachePut(int age) { return helloService.cachePut(age); }
最後管理小結一下Spring提供的幾個緩存註解
@Cacheable
: 緩存存在,則從緩存取;不然執行方法,並將返回結果寫入緩存@CacheEvit
: 失效緩存@CachePut
: 更新緩存@Caching
: 都註解組合上面雖然說能夠知足常見的緩存使用場景,可是有一個很是重要的點沒有說明,緩存失效時間應該怎麼設置???
如何給每一個緩存設置不一樣的緩存失效時間,咱麼下篇博文見,我是一灰灰,歡迎關注長草的公衆號一灰灰blog
盡信書則不如,以上內容,純屬一家之言,因我的能力有限,不免有疏漏和錯誤之處,如發現bug或者有更好的建議,歡迎批評指正,不吝感激
下面一灰灰的我的博客,記錄全部學習和工做中的博文,歡迎你們前去逛逛