当前位置: 首页 > news >正文

Spring 缓存注解这样用,太香了!

作者最近在开发公司项目时使用到 Redis 缓存,并在翻看前人代码时,看到了一种关于 @Cacheable 注解的自定义缓存有效期的解决方案,感觉比较实用,因此作者自己拓展完善了一番后分享给各位。

Spring 缓存常规配置

Spring Cache 框架给我们提供了 @Cacheable 注解用于缓存方法返回内容。但是 @Cacheable 注解不能定义缓存有效期。这样的话在一些需要自定义缓存有效期的场景就不太实用。

按照 Spring Cache 框架给我们提供的 RedisCacheManager 实现,只能在全局设置缓存有效期。这里给大家看一个常规的 CacheConfig 缓存配置类,代码如下,

@EnableCaching
@Configuration
public class CacheConfig extends CachingConfigurerSupport {...private RedisSerializer<String> keySerializer() {return new StringRedisSerializer();}private RedisSerializer<Object> valueSerializer() {return new GenericFastJsonRedisSerializer();}public static final String CACHE_PREFIX = "crowd:";@Beanpublic CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {// 配置序列化(解决乱码的问题)RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()//设置key为String.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer()))//设置value为自动转Json的Object.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer())).computePrefixWith(name -> CACHE_PREFIX + name  + ":").entryTtl(Duration.ofSeconds(600));RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(Objects.requireNonNull(redisConnectionFactory));return new RedisCacheManager(redisCacheWriter, config);}
}

这里面简单对 RedisCacheConfiguration 缓存配置做一下说明:

  1. serializeKeysWith():设置 Redis 的 key 的序列化规则。

  2. erializeValuesWith():设置 Redis 的 value 的序列化规则。

  3. computePrefixWith():计算 Redis 的 key 前缀。

  4. entryTtl():全局设置 @Cacheable 注解缓存的有效期。

那么使用如上配置生成的 Redis 缓存 key 名称是什么样得嘞?这里用开源项目 crowd-adminConfigServiceImpl 类下 getValueByKey(String key) 方法举例,

@Cacheable(value = "configCache", key = "#root.methodName + '_' + #root.args[0]")
@Override
public String getValueByKey(String key) {QueryWrapper<Config> wrapper = new QueryWrapper<>();wrapper.eq("configKey", key);Config config = getOne(wrapper);if (config == null) {return null;}return config.getConfigValue();
}

执行此方法后,Redis 中缓存 key 名称如下,

crowd:configCache:getValueByKey_sys.name

ttl 过期时间是 287,跟我们全局设置的 300 秒基本是一致的。此时假如我们想把 getValueByKey 方法的缓存有效期单独设置为 600 秒,那我们该如何操作嘞?

@Cacheable 注解默认是没有提供有关缓存有效期设置的。想要单独修改 getValueByKey 方法的缓存有效期只能修改全局的缓存有效期。那么有没有别的方法能够为 getValueByKey 方法单独设置缓存有效期嘞?当然是有的,大家请往下看。

自定义 MyRedisCacheManager 缓存

其实我们可以通过自定义 MyRedisCacheManager 类继承 Spring Cache 提供的 RedisCacheManager 类后,重写 createRedisCache(String name, RedisCacheConfiguration cacheConfig) 方法来完成自定义缓存有效期的功能,代码如下,

public class MyRedisCacheManager extends RedisCacheManager {public MyRedisCacheManager(RedisCacheWriter cacheWriter, RedisCacheConfiguration defaultCacheConfiguration) {super(cacheWriter, defaultCacheConfiguration);}@Overrideprotected RedisCache createRedisCache(String name, RedisCacheConfiguration cacheConfig) {String[] array = StringUtils.split(name, "#");name = array[0];// 解析 @Cacheable 注解的 value 属性用以单独设置有效期if (array.length > 1) {long ttl = Long.parseLong(array[1]);cacheConfig = cacheConfig.entryTtl(Duration.ofSeconds(ttl));}return super.createRedisCache(name, cacheConfig);}
}

MyRedisCacheManager 类逻辑如下,

  1. 继承 Spring Cache 提供的 RedisCacheManager 类。

  2. 重写 createRedisCache(String name, RedisCacheConfiguration cacheConfig) 方法。

  3. 解析 name 参数,根据 # 字符串进行分割,获取缓存 key 名称以及缓存有效期。

  4. 重新设置缓存 key 名称以及缓存有效期。

  5. 调用父类的 createRedisCache(name, cacheConfig) 方法来完成缓存写入。

接着我们修改下 CacheConfig 类的 cacheManager 方法用以使用 MyRedisCacheManager 类。代码如下,

@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {return new MyRedisCacheManager(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory), defaultCacheConfig());
}private RedisCacheConfiguration defaultCacheConfig() {return RedisCacheConfiguration.defaultCacheConfig().serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer())).serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer())).computePrefixWith(name -> CACHE_PREFIX + name  + ":").entryTtl(Duration.ofSeconds(600));
}

最后在使用 @Cacheable 注解时,在原有 value 属性的 configCache 值后添加 #600,单独标识缓存有效期。代码如下,

@Cacheable(value = "configCache#600", key = "#root.methodName + '_' + #root.args[0]")
@Override
public String getValueByKey(String key) {...
}

看下 getValueByKey 方法生成的 Redis 缓存 key 有效期是多久。如下,

OK,看到是 590 秒有效期后,我们就大功告成了。到这里我们就完成了对 @Cacheable 注解的自定义缓存有效期功能开发。

关注公众号【waynblog】每周分享技术干货、开源项目、实战经验、国外优质文章翻译等,您的关注将是我的更新动力!

相关文章:

  • 基于8086汽车智能小车控制系统
  • 征服地球极限,中国极地科考与登峰事业的“御寒”之旅
  • 300.最长递增子序列
  • 数据权限-字段权限【实践篇-结合相关业务详细讲解如何实现】(基于若依框架)
  • 关于DDD的贫血模型和充血模型到底是什么区别?
  • JS+CSS随机点名详细介绍复制可用(可自己添加人名)
  • 合肥工业大学计算机网络实验一
  • 力扣21.合并两个有序链表
  • torch.mv
  • os_cfg.h、os_cpu.h和ucos_ii.h
  • 基于SSM的旅游管理系统的设计与实现
  • 租用网站服务器的六大指标
  • 怎么批量获取文件名,并保存到excel?
  • 【前段基础入门之】=>CSS3新特性 文本多列 布局
  • MeterSphere | 前端入参加密
  • Brief introduction of how to 'Call, Apply and Bind'
  • canvas 五子棋游戏
  • ES2017异步函数现已正式可用
  • iOS | NSProxy
  • js数组之filter
  • Just for fun——迅速写完快速排序
  • Linux编程学习笔记 | Linux IO学习[1] - 文件IO
  • Python_OOP
  • Redis 中的布隆过滤器
  • SpiderData 2019年2月13日 DApp数据排行榜
  • UMLCHINA 首席专家潘加宇鼎力推荐
  • 大数据与云计算学习:数据分析(二)
  • 工作手记之html2canvas使用概述
  • 开源中国专访:Chameleon原理首发,其它跨多端统一框架都是假的?
  • 利用阿里云 OSS 搭建私有 Docker 仓库
  • 前嗅ForeSpider采集配置界面介绍
  • 通过几道题目学习二叉搜索树
  • 系统认识JavaScript正则表达式
  • ​ArcGIS Pro 如何批量删除字段
  • ​html.parser --- 简单的 HTML 和 XHTML 解析器​
  • # C++之functional库用法整理
  • #1015 : KMP算法
  • (1)SpringCloud 整合Python
  • (NSDate) 时间 (time )比较
  • (Redis使用系列) Springboot 使用Redis+Session实现Session共享 ,简单的单点登录 五
  • (TOJ2804)Even? Odd?
  • (翻译)terry crowley: 写给程序员
  • (附源码)ssm失物招领系统 毕业设计 182317
  • (七)MySQL是如何将LRU链表的使用性能优化到极致的?
  • (全部习题答案)研究生英语读写教程基础级教师用书PDF|| 研究生英语读写教程提高级教师用书PDF
  • (十六)Flask之蓝图
  • (转)菜鸟学数据库(三)——存储过程
  • .NET gRPC 和RESTful简单对比
  • .NET 常见的偏门问题
  • .NET/C# 在 64 位进程中读取 32 位进程重定向后的注册表
  • .Net6使用WebSocket与前端进行通信
  • .net反编译的九款神器
  • .net中我喜欢的两种验证码
  • @Autowired注解的实现原理
  • [ IOS ] iOS-控制器View的创建和生命周期