Spring Boot中如何基于@Cacheable注解按方法参数实现Redis缓存?
问题1:未配置key参数时如何区分不同category的缓存
@Cacheable的value属性本质是缓存分区名称,仅用来做同业务缓存的归类,并不是实际存储的缓存Key的全部内容。
Spring Cache有默认的Key生成规则,使用SimpleKeyGenerator实现:
- 当方法没有入参时,使用
SimpleKey.EMPTY作为Key - 当方法只有1个入参时,直接使用该入参实例作为Key
- 当方法有多个入参时,使用包含所有入参的
SimpleKey实例作为Key
你传入的categoryA和categoryB属于不同实例,只要Category类正常重写了equals()和hashCode()方法,二者计算出来的哈希值不同,生成的缓存Key自然不同。最终存储到Redis中的Key格式为productCache::[生成的Key值],因此可以区分不同category的返回结果。
问题2:显式配置key="#category"后效果和之前一致是否正常
这是完全正常的现象,不存在配置遗漏。
因为你的方法只有一个category入参,默认的Key生成策略刚好就是用这个入参作为Key,你显式指定key="#category"的结果和默认规则完全一致,所以运行效果没有任何区别。
只有当你需要自定义Key规则时才需要额外配置key属性,例如:方法有多个入参但只需用部分参数生成Key、需要拼接固定前缀、需要取参数的某个属性(比如key="#category.id")作为Key等场景。
问题3:手动获取缓存的正确写法
你给出的写法是错误的。cacheManager.getCache()的入参是缓存分区名称,也就是你在@Cacheable中配置的value值productCache,不需要拼接任何参数。拿到对应分区的缓存实例后,再传入Key值获取对应缓存,正确写法参考:
// 1. 获取productCache分区的缓存实例 Cache productCache = cacheManager.getCache("productCache"); if (productCache != null) { // 2. 传入Key(即category实例)获取缓存 Cache.ValueWrapper wrapper = productCache.get(category); if (wrapper != null) { List<ProductDTO> cachedList = (List<ProductDTO>) wrapper.get(); } }
你原写法中拼接#+category的逻辑,相当于要查找名为productCache#xxx的缓存分区,这个分区不存在,自然无法拿到缓存数据。
内容的提问来源于stack exchange,提问作者user16409822
相关产品推荐
相关产品推荐

