Spring 之 @Cacheable 緩存使用教程

1、@Cacheable 指定使用緩存

定義個 Controller ,在方法上加上注解?@Cacheable,配置要使用哪些緩存,比如 myMapCache 表示一級緩存是 Map,myRedisCache 表示二級緩存是 Redis。并配置緩存 key。 key 由 SPEL 表達式組成,Spring 可以動態解析生成緩存 key。

提示:myMapCache、myRedisCache 均為注入 Spring 緩存的名稱

@RestController
public class CachingAnnoController {@Cacheable(cacheNames = {"myMapCache","myRedisCache"},key = "'test_'+#key")@RequestMapping("/cachingAnno")public String cachingAnno(String key,String value){System.out.println("查詢數據庫值 = " + value);return "value";}
}

2、@EnableCaching 開啟緩存功能

用過 @Cacheable 注解的都知道,要開啟緩存功能必須通過 @EnableCaching 注解。代碼如下:

@ComponentScan(value = "com.gwm")
@Configuration
@EnableCaching
public class SpringConfig {}

3、引入具體要使用的緩存—實現 Cache 接口

上述 @EnableCaching、@Cacheable 都是 Spring 提供的基本緩存框架,而具體的緩存需要自己引入。比如現在自己定義兩個緩存:MyMapCache 類 、MyRedisCache 類。然后實現接口方法。

Spring 提供 Cache 作為標準化接口,具體的實現 Spring 不管,你自己去實現。但是 Spring 也是有幾個默認實現的,比如:CaffeineCache、EhCacheCache、ConcurrentMapCache、JCacheCache 等。

public class MyMapCache implements Cache {public static final Map<Object, Object> map = new ConcurrentHashMap<>();private String cacheName;public MyMapCache(String cacheName) {this.cacheName = cacheName;}@Overridepublic String getName() {return cacheName;}@Overridepublic Object getNativeCache() {return null;}@Overridepublic ValueWrapper get(Object key) {System.out.println(">>>>>>我是 MyMapCache 緩存中的 get() 方法");Object o = map.get(key);if (Objects.nonNull(o)) {return new SimpleValueWrapper(o);}return null;}@Overridepublic <T> T get(Object key, Class<T> type) {return (T)map.get(key);}@Overridepublic <T> T get(Object key, Callable<T> valueLoader) {return (T)map.get(key);}@Overridepublic void put(Object key, Object value) {System.out.println(">>>>>>我是 MyMapCache 緩存中的 put() 方法");map.put(key, value);}@Overridepublic void evict(Object key) {map.remove(key);}@Overridepublic void clear() {map.clear();}
}

MyRedisCache 類實現,代碼如下:

public class MyRedisCache implements Cache {private String cacheName;private RedisTemplate<Object,Object> redisTemplate;public MyRedisCache(String cacheName, RedisTemplate<Object, Object> redisTemplate) {this.cacheName = cacheName;this.redisTemplate = redisTemplate;}@Overridepublic String getName() {return cacheName;}@Overridepublic Object getNativeCache() {return this;}@Overridepublic ValueWrapper get(Object key) {System.out.println(">>>>>>我是 MyRedisCache 緩存中的 get() 方法");Object o = redisTemplate.opsForValue().get(key);if (Objects.nonNull(o)) {return new SimpleValueWrapper(o);}return null;}@Overridepublic <T> T get(Object key, Class<T> type) {return null;}@Overridepublic <T> T get(Object key, Callable<T> valueLoader) {return null;}@Overridepublic void put(Object key, Object value) {System.out.println(">>>>>>我是 MyRedisCache 緩存中的 put() 方法");redisTemplate.opsForValue().set(key,value);redisTemplate.expire(key, Duration.ofMillis(3000));}@Overridepublic void evict(Object key) {redisTemplate.delete(key);}@Overridepublic void clear() {redisTemplate.execute((RedisCallback<Object>) conn->{// 清空所有緩存數據,要格外注意這個操作,很危險conn.flushDb();return ">>>>>>flush db success!";});}
}

4、緩存管理類—實現 CacheManager 接口

自定義緩存定義完之后,光擺在這里肯定是不能起作用的,還需要借助 Spring 標準化接口 CacheManager 類來把緩存加入到緩存切面邏輯中。

比如實現 MyMapCache 緩存管理類 MyMapCacheManager,代碼如下:

public class MyMapCacheManager implements CacheManager {@Overridepublic Cache getCache(String name) {return new MyMapCache(name);}@Overridepublic Collection<String> getCacheNames() {return Arrays.asList("myMapCache");}
}

實現 MyRedisCache 緩存管理類 MyRedisCacheManager,代碼如下:

public class MyRedisCacheManager implements CacheManager {@Overridepublic Cache getCache(String name) {return new MyRedisCache(name,redisTemplate);}@Overridepublic Collection<String> getCacheNames() {return Arrays.asList("myRedisCache");}
}

然后在配置入口類中通過 @Bean 引用具體的緩存。代碼如下:

@Configuration
public class MyRedisMainConfig {@Resourceprivate RedisTemplate<Object,Object> redisTemplate;@Beanpublic MyMapCache myMapCache() {MyMapCache myMapCache = new MyMapCache("myMapCache");return myMapCache;}@Beanpublic MyRedisCache myRedisCache() {MyRedisCache myRedisCache = new MyRedisCache("myRedisCache",redisTemplate);return myRedisCache;}@Beanpublic MyRedisCacheManager cacheManager() {MyRedisCacheManager redisCacheManager = new MyRedisCacheManager();return redisCacheManager;}// @Bean public MyMapCacheManager cacheManager() {MyRedisCacheManager redisCacheManager = new MyRedisCacheManager();return redisCacheManager;}}

但是發現使用具體的管理類引入緩存,只能引入對應的緩存。比如 MyRedisCacheManager 管理類就只能引入 MyRedisCache 緩存,不能引入 MyMapCache。所以這是個弊端。如果想要使用雙緩存,那怎么辦呢?

5、雙緩存使用—實現 AbstractCacheManager 抽象類

該抽象類提供 loadCaches() 方法,可以獲取到所有 Cache 接口實現類。所以這里能夠獲取到所有緩存。那么肯定是可以使用雙緩存。比如 MySimpleCacheManager 類實現,代碼如下:

public class MySimpleCacheManager extends AbstractCacheManager implements ApplicationContextAware {private static final List<Cache> list = new ArrayList<>();private ApplicationContext context;/*** 直接實現 AbstractCacheManager 抽象類的鉤子方法,該類已經寫好模版方法* 當執行的時候,如果 MyGuavaCacheManager 管理類 @Bean 的話,就會勾到這個方法邏輯* @return*/@Overrideprotected Collection<? extends Cache> loadCaches() {return list;}@Overridepublic void afterPropertiesSet() {Map<String, Cache> beansOfType = context.getBeansOfType(Cache.class);list.addAll(beansOfType.values());}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException this.context = applicationContext;}
}

然后再配置入口類,代碼如下:

@Configuration
public class MyRedisMainConfig {@Resourceprivate RedisTemplate<Object,Object> redisTemplate;@Beanpublic MyMapCache myMapCache() {MyMapCache myMapCache = new MyMapCache("myMapCache");return myMapCache;}@Beanpublic MyRedisCache myRedisCache() {MyRedisCache myRedisCache = new MyRedisCache("myRedisCache",redisTemplate);return myRedisCache;}@Beanpublic MySimpleCacheManager cacheManager(@Qualifier("myMapCache") MyMapCache myMapCache,@Qualifier("myRedisCache") MyRedisCache myRedisCache,@Qualifier("myGuavaCache") MyGuavaCache myGuavaCache) {SimpleCacheManager simpleCacheManager = new SimpleCacheManager();simpleCacheManager.setCaches(Arrays.asList(myMapCache,myRedisCache,myGuavaCache));return simpleCacheManager;}
}

最終通過注入一個緩存管理類 MySimpleCacheManager 就可以使用到三個緩存。美滋滋。最終要使用,就通過?@Cacheable(cacheNames = {“myMapCache”,“myRedisCache”},key = “‘test_’+#key”)?即可使用 myMapCache、myRedisCache 緩存。如果還需要使用 myGuavaCache,直接往數組中添加即可。

6、 RedisCacheManager 內置類

在使用 Redis 緩存時,Spring 早已對其包裝完成,只需要引入 spring-data-redis 包即可。我們不需要寫 MyRedisCacheManager 類,Spring 早就提供 RedisCacheManager 類管理 Redis 緩存 。所以你只需能夠連接好 Redis 。然后通過 @Bean 將?RedisCacheManager?類注入即可使用 Redis 緩存。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:
http://www.pswp.cn/news/206727.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/206727.shtml
英文地址,請注明出處:http://en.pswp.cn/news/206727.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

異常檢測 | MATLAB實現BiLSTM(雙向長短期記憶神經網絡)數據異常檢測

異常檢測 | MATLAB實現BiLSTM(雙向長短期記憶神經網絡)數據異常檢測 目錄 異常檢測 | MATLAB實現BiLSTM(雙向長短期記憶神經網絡)數據異常檢測效果一覽基本介紹模型準備模型設計參考資料效果一覽 基本介紹 訓練一個雙向 LSTM 自動編碼器來檢測機器是否正常工作。 自動編碼器接受…

CleanMyMac X2024最新版本軟件實用性測評

信大多數MAC用戶都較為了解&#xff0c;Mac雖然有著許多亮點的性能&#xff0c;但是讓用戶叫苦不迭的還其硬盤空間小的特色&#xff0c;至于很多人因為文件堆積以及軟件緩存等&#xff0c;造成系統空間內存不夠使用的情況。于是清理工具就成為了大多數MAC用戶使用頻率較高的實用…

二十一章網絡通信

計算機網絡實現了多臺計算機間的互聯&#xff0c;使得它們彼此之間能夠進行數據交流。網絡應用程序就是在已連接的不同計算機上運行的程序&#xff0c;這些程序借助于網絡協議&#xff0c;相互之間可以交換數據。編寫網絡應用程序前&#xff0c;首先必須明確所要使用的網絡協議…

數據采集工具的大全【都是免費值得收藏】

數據是推動業務成功的關鍵之一。為了獲取準確、全面的信息&#xff0c;數據采集成為了許多企業和個人的必備工作。本文將專注于數據采集工具&#xff0c;探討其在全網和指定網站采集方面的優勢&#xff0c;為大家提供對比分析&#xff0c;以幫助大家找到最適合的數據采集利器。…

算法復習——6種排序方法的簡單回顧

算法復習——6種排序方法的簡單回顧 常見排序方法&#xff1a;冒泡排序、選擇排序、插入排序、堆排序、歸并排序、快速排序的簡單回顧 冒泡排序 重復“從序列右邊開始比較相鄰兩個數字的大小,再根據結果交換兩個數字的位置” 在冒泡排序中&#xff0c;第 1 輪需要比較 n - 1…

Tair(1):Tair介紹

1 介紹 ? 在Tair出現之前的很長一段時間里&#xff0c;像redis、memcache這些知名NoSql數據庫是不支持分布式的&#xff0c;在這樣的背景下&#xff0c;由淘寶網自主開發并在2010.6開源的一個高性能、高擴展、高可靠分布式緩存&#xff0c;類似map的key/value結構&#xff0c…

使用單例模式+觀察者模式實現參數配置實時更新

使用vector存儲觀察者列表 #include <iostream> #include <vector> #include <functional> #include <algorithm>// 配置參數結構體 struct MyConfigStruct {int parameter1;std::string parameter2; };class Config { public:using Observer std::f…

hive 命令行中使用 replace 和nvl2 函數報錯

1.有時候在命令行的情況下使用 replace 函數時會報錯 這個時候可以使用 translate 代替 2.有時候使用 nvl2() 函數的時候會報錯 這個時候可以用 case when 來代替

【Spring 源碼】 深入理解 Bean 定義之 BeanDefinition

&#x1f680; 作者主頁&#xff1a; 有來技術 &#x1f525; 開源項目&#xff1a; youlai-mall &#x1f343; vue3-element-admin &#x1f343; youlai-boot &#x1f33a; 倉庫主頁&#xff1a; Gitee &#x1f4ab; Github &#x1f4ab; GitCode &#x1f496; 歡迎點贊…

兩數之和問題

更好的閱讀體驗請點擊 兩數之和。 題目&#xff1a;兩數之和 ? 給定一個整數數組 nums 和一個整數目標值 target&#xff0c;請你在該數組中找出 和為目標值 target 的那 兩個 整數&#xff0c;并返回它們的數組下標。 ? 你可以假設每種輸入只會對應一個答案。但是&#xff…

MetricBeat監控Redis

目錄 一、安裝部署 二、開啟Redis監控模塊 三、編輯Redis配置文件 四、啟動Metricbeat 五、查看監控圖表 一、安裝部署 metriceat的安裝部署參考章節&#xff1a; 監控組件>Metricbeat安裝使用&#xff0c;這里不再贅述。 二、開啟Redis監控模塊 進入metricbeat安裝目錄…

【每日一題】出租車的最大盈利

文章目錄 Tag題目來源解題思路方法一&#xff1a;遞歸方法二&#xff1a;遞歸記錄數組記憶化搜索方法三&#xff1a;動態規劃&#xff08;遞推&#xff09; 寫在最后 Tag 【遞歸】【記憶化搜索】【動態規劃】【數組】【2023-12-08】 題目來源 2008. 出租車的最大盈利 解題思路…

【EI會議征稿中】2024年第四屆人工智能、自動化與高性能計算國際會議(AIAHPC 2024)

2024年第四屆人工智能、自動化與高性能計算國際會議&#xff08;AIAHPC 2024&#xff09; 2024 4th International Conference on Artificial Intelligence, Automation and High Performance Computing 2024第四屆人工智能、自動化與高性能計算國際會議(AIAHPC 2024)將于20…

藍橋杯從零開始備戰(Python組)---基礎知識篇

第一次嘗試報名藍橋杯的Python組&#xff0c;好好備戰&#xff0c;希望省賽可以拿獎&#xff01;目前是整理了一些Python的常用函數和常用內置庫&#xff0c;后面可能會開始刷題&#xff0c;如果有比較需要記住的知識點&#xff0c;會再寫一篇刷題篇 一、輸入輸出 1.輸入字符…

游戲被攻擊怎么辦

隨著科技的進步和互聯網的普及&#xff0c;游戲行業也正在經歷前所未有的變革。玩家們不再滿足于傳統的線下游戲&#xff0c;而是轉向了線上游戲。然而&#xff0c;隨著游戲的線上化&#xff0c;游戲安全問題也日益凸顯。游戲受到攻擊是游戲開發者永遠的痛點&#xff0c;談“D“…

HomeAssistant添加HACS插件并實現公網控制米家,HomeKit等智能家居

HomeAssistant添加HACS插件并實現公網控制米家&#xff0c;HomeKit等智能家居 文章目錄 HomeAssistant添加HACS插件并實現公網控制米家&#xff0c;HomeKit等智能家居基本條件一、下載HACS源碼二、添加HACS集成三、綁定米家設備 ? 上文介紹了如何實現群暉Docker部署HomeAssist…

【嵌入式開發 Linux 常用命令系列 4.1 -- git push 遠程分支與本地分支查看】

文章目錄 概述git push 語法步驟1&#xff1a;git 遠程主機名查看步驟2&#xff1a;git 遠程分支名查看步驟3&#xff1a;git 本地分支名查看示例演示 概述 在日常工作中&#xff0c;將代碼 git clone 本地之后&#xff0c;或者使用repo init && repo sync 之后不知道…

SQLserver截取字符串

當我們存的數據是json的時候可以全部取出在模糊查詢但是有多個重復數據的時候就沒辦法準確的模糊出來這個時候我們就需要用的字符串截取 --創建函數create FUNCTION [dbo].[Fmax] (str varchar(50),start VARCHAR(50),length VARCHAR(50)) RETURNS varchar(max) AS BEGINDEC…

商品詳情頁評論和評論列表評論的排序html代碼

以下是一個簡單的商品詳情頁的 HTML 代碼示例&#xff1a; <!DOCTYPE html> <html> <head><title>商品詳情頁</title><style>/* CSS 樣式可以在這里添加 */</style> </head> <body><h1>商品詳情頁</h1><…

7-1 查找書籍

給定n本書的名稱和定價&#xff0c;本題要求編寫程序&#xff0c;查找并輸出其中定價最高和最低的書的名稱和定價。 輸入格式: 輸入第一行給出正整數n&#xff08;<10&#xff09;&#xff0c;隨后給出n本書的信息。每本書在一行中給出書名&#xff0c;即長度不超過30的字…