網(wǎng)站首頁 編程語言 正文
1、@Cacheable 指定使用緩存
定義個 Controller ,在方法上加上注解?@Cacheable
,配置要使用哪些緩存,比如 myMapCache 表示一級緩存是 Map,myRedisCache 表示二級緩存是 Redis。并配置緩存 key。 key 由 SPEL 表達式組成,Spring 可以動態(tài)解析生成緩存 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("查詢數(shù)據(jù)庫值 = " + value);
return "value";
}
}
2、@EnableCaching 開啟緩存功能
用過 @Cacheable 注解的都知道,要開啟緩存功能必須通過 @EnableCaching 注解。代碼如下:
@ComponentScan(value = "com.gwm")
@Configuration
@EnableCaching
public class SpringConfig {
}
3、引入具體要使用的緩存—實現(xiàn) Cache 接口
上述 @EnableCaching、@Cacheable 都是 Spring 提供的基本緩存框架,而具體的緩存需要自己引入。比如現(xiàn)在自己定義兩個緩存:MyMapCache 類 、MyRedisCache 類。然后實現(xiàn)接口方法。
Spring 提供 Cache 作為標準化接口,具體的實現(xiàn) Spring 不管,你自己去實現(xiàn)。但是 Spring 也是有幾個默認實現(xiàn)的,比如: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;
}
@Override
public String getName() {
return cacheName;
}
@Override
public Object getNativeCache() {
return null;
}
@Override
public ValueWrapper get(Object key) {
System.out.println(">>>>>>我是 MyMapCache 緩存中的 get() 方法");
Object o = map.get(key);
if (Objects.nonNull(o)) {
return new SimpleValueWrapper(o);
}
return null;
}
@Override
public <T> T get(Object key, Class<T> type) {
return (T)map.get(key);
}
@Override
public <T> T get(Object key, Callable<T> valueLoader) {
return (T)map.get(key);
}
@Override
public void put(Object key, Object value) {
System.out.println(">>>>>>我是 MyMapCache 緩存中的 put() 方法");
map.put(key, value);
}
@Override
public void evict(Object key) {
map.remove(key);
}
@Override
public void clear() {
map.clear();
}
}
MyRedisCache 類實現(xiàn),代碼如下:
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;
}
@Override
public String getName() {
return cacheName;
}
@Override
public Object getNativeCache() {
return this;
}
@Override
public 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;
}
@Override
public <T> T get(Object key, Class<T> type) {
return null;
}
@Override
public <T> T get(Object key, Callable<T> valueLoader) {
return null;
}
@Override
public void put(Object key, Object value) {
System.out.println(">>>>>>我是 MyRedisCache 緩存中的 put() 方法");
redisTemplate.opsForValue().set(key,value);
redisTemplate.expire(key, Duration.ofMillis(3000));
}
@Override
public void evict(Object key) {
redisTemplate.delete(key);
}
@Override
public void clear() {
redisTemplate.execute((RedisCallback<Object>) conn->{
// 清空所有緩存數(shù)據(jù),要格外注意這個操作,很危險
conn.flushDb();
return ">>>>>>flush db success!";
});
}
}
4、緩存管理類—實現(xiàn) CacheManager 接口
自定義緩存定義完之后,光擺在這里肯定是不能起作用的,還需要借助 Spring 標準化接口 CacheManager 類來把緩存加入到緩存切面邏輯中。
比如實現(xiàn) MyMapCache 緩存管理類 MyMapCacheManager,代碼如下:
public class MyMapCacheManager implements CacheManager {
@Override
public Cache getCache(String name) {
return new MyMapCache(name);
}
@Override
public Collection<String> getCacheNames() {
return Arrays.asList("myMapCache");
}
}
實現(xiàn) MyRedisCache 緩存管理類 MyRedisCacheManager,代碼如下:
public class MyRedisCacheManager implements CacheManager {
@Override
public Cache getCache(String name) {
return new MyRedisCache(name,redisTemplate);
}
@Override
public Collection<String> getCacheNames() {
return Arrays.asList("myRedisCache");
}
}
然后在配置入口類中通過 @Bean 引用具體的緩存。代碼如下:
@Configuration
public class MyRedisMainConfig {
@Resource
private RedisTemplate<Object,Object> redisTemplate;
@Bean
public MyMapCache myMapCache() {
MyMapCache myMapCache = new MyMapCache("myMapCache");
return myMapCache;
}
@Bean
public MyRedisCache myRedisCache() {
MyRedisCache myRedisCache = new MyRedisCache("myRedisCache",redisTemplate);
return myRedisCache;
}
@Bean
public MyRedisCacheManager cacheManager() {
MyRedisCacheManager redisCacheManager = new MyRedisCacheManager();
return redisCacheManager;
}
// @Bean
public MyMapCacheManager cacheManager() {
MyRedisCacheManager redisCacheManager = new MyRedisCacheManager();
return redisCacheManager;
}
}
但是發(fā)現(xiàn)使用具體的管理類引入緩存,只能引入對應的緩存。比如 MyRedisCacheManager 管理類就只能引入 MyRedisCache 緩存,不能引入 MyMapCache。所以這是個弊端。如果想要使用雙緩存,那怎么辦呢?
5、雙緩存使用—實現(xiàn) AbstractCacheManager 抽象類
該抽象類提供 loadCaches() 方法,可以獲取到所有 Cache 接口實現(xiàn)類。所以這里能夠獲取到所有緩存。那么肯定是可以使用雙緩存。比如 MySimpleCacheManager 類實現(xiàn),代碼如下:
public class MySimpleCacheManager extends AbstractCacheManager implements ApplicationContextAware {
private static final List<Cache> list = new ArrayList<>();
private ApplicationContext context;
/**
* 直接實現(xiàn) AbstractCacheManager 抽象類的鉤子方法,該類已經(jīng)寫好模版方法
* 當執(zhí)行的時候,如果 MyGuavaCacheManager 管理類 @Bean 的話,就會勾到這個方法邏輯
* @return
*/
@Override
protected Collection<? extends Cache> loadCaches() {
return list;
}
@Override
public void afterPropertiesSet() {
Map<String, Cache> beansOfType = context.getBeansOfType(Cache.class);
list.addAll(beansOfType.values());
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
this.context = applicationContext;
}
}
然后再配置入口類,代碼如下:
@Configuration
public class MyRedisMainConfig {
@Resource
private RedisTemplate<Object,Object> redisTemplate;
@Bean
public MyMapCache myMapCache() {
MyMapCache myMapCache = new MyMapCache("myMapCache");
return myMapCache;
}
@Bean
public MyRedisCache myRedisCache() {
MyRedisCache myRedisCache = new MyRedisCache("myRedisCache",redisTemplate);
return myRedisCache;
}
@Bean
public 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,直接往數(shù)組中添加即可。
6、 RedisCacheManager 內置類
在使用 Redis 緩存時,Spring 早已對其包裝完成,只需要引入 spring-data-redis 包即可。我們不需要寫 MyRedisCacheManager 類,Spring 早就提供 RedisCacheManager 類管理 Redis 緩存 。所以你只需能夠連接好 Redis 。然后通過 @Bean 將?RedisCacheManager?類注入即可使用 Redis 緩存。
原文鏈接:https://blog.csdn.net/fygkchina/article/details/134725916
- 上一篇:沒有了
- 下一篇:沒有了
相關推薦
- 2022-09-09 python中gevent庫的用法詳情_python
- 2022-12-13 詳解如何魔改Retrofit實例_Android
- 2022-06-22 C語言詳解Z字形變換排列的實現(xiàn)_C 語言
- 2022-03-22 C++類常量和類枚舉_C 語言
- 2023-03-29 Redis內存碎片原理深入分析_Redis
- 2022-02-13 自動化進行Pod的擴縮容-HPA
- 2022-05-08 Python函數(shù)命名空間和作用域(Local與Global)_python
- 2022-11-25 C++關鍵字之likely和unlikely詳解_C 語言
- 欄目分類
-
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學習環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結構-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支