Spring @Cacheable缓存注解

一、简介

缓存介绍

缓存,在我们的日常开发中用的非常多,是我们应对各种性能问题支持高并发的一大利器。

  • Spring 从 3.1 开始就引入了缓存的支持。定义了如下两个接口来统一支持不同的缓存技术。

    • org.springframework.cache.Cache
    • org.springframework.cache.CacheManager
  • 我们熟知的缓存有:堆缓存(Ehcache3.xGuava CacheCaffeine等)、堆外缓存(Ehcache3.xMapDB等)、分布式缓存RedisMemcached等)等等。

  • 常用的缓存注解:@EnableCaching@Cacheable@CachePut@CacheEvict

Cache 和 CacheManager 接口说明

  • Cache 接口包含缓存的各种操作集合,你操作缓存就是通过这个接口来操作的。
  • Cache 接口下 Spring 提供了各种 xxxCache 的实现,比如:RedisCache、EhCache、ConcurrentMapCache等。
  • CacheManager 定义了创建、配置、获取、管理和控制多个唯一命名的 Cache。这些 Cache 存在于 CacheManager 的上下文中。

二、缓存实战

1.开启缓存

在 SpringBoot 的启动类上添加注解@EnableCaching

2.@Cacheable

@Cacheable 的作用 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存。

常用属性:

  • cacheNamesvalue:用来指定缓存组件名称。

    复制代码
    @Cacheable(cacheNames = "users", key="#id")
    public User getUser(Integer id) {}
  • key:缓存数据的 key,可以用它来指定。默认使用所有参数的值进行组合。(key可以使用 spEL 表达式来编写)。

    复制代码
    @Cacheable(cacheNames = "usersBySpEL", key="#root.methodName + '[' + #id + ']'")
    public User getUserBySpEL(Integer id) {}
  • keyGenerator:key 的生成器。key 和 keyGenerator 二选一使用。

    复制代码
    @Cacheable(cacheNames = "userByKeyGenerator", keyGenerator = "myKeyGenerator")
    public User getUserByKeyGenerator(Integer id) {}
  • condition:指定符合条件的情况下才缓存。

    复制代码
    @Cacheable(cacheNames = "userByCondition", condition = "#id > 1")
    public User getUserByCondition(Integer id) {}
  • unless:指定不符合条件的情况下才缓存。(可以获取到结果进行判断,通过 #result 获取方法结果,unless,汉语意思,除非,指会缓存,除了。。。之外)。

    复制代码
    @Cacheable(cacheNames = "userByUnless", unless = "#id > 1")
    public User getUserByUnless(Integer id) {}
  • sync:是否使用异步模式。

3.@CachePut

@CachePut 的作用 主要针对配置,能够根据方法的请求参数对其结果进行缓存。

  • 区别于 @Cacheable,它每次都会触发真实方法的调用,可以保证缓存的一致性。
  • 属性与 @Cacheable 类同。
复制代码
@CachePut(cacheNames = "users" , key = "#user.id")
public User addUser(User user) {}
4.@CacheEvict

@CacheEvict 的作用 主要针对方法配置,能够根据一定的条件对缓存进行清空

常用属性

  • cacheNamesvalue:用来指定缓存组件名称。

  • key:缓存数据的 key,可以用它来指定。默认使用所有参数的值进行组合。(key可以使用 spEL 表达式来编写)。

  • condition:指定符合条件的情况下的缓存。

  • allEntries:是否清空所有缓存,缺省为false。

  • beforeInvocation:是否在方法执行前就清空,缺省为false,缺省情况下,如果方法执行抛异常,则不会清空缓存。

    @CacheEvict(cacheNames = "users", key = "#id")
    public void delUserCache(Integer id) {}

5.@CacheConfig

@CacheConfig 的作用 主要针对类配置,能够设置当前类中 @Cacheable 的 value 属性默认值。当然如果 @Cacheable 设置了 value,还是以设置的值为准。

常用属性

  • cacheNames: 指定缓存名称默认值。
6.@Caching

@Caching 的作用 主要针对方法配置,能够组合多个Cache注解。比如用户新增成功后,我们可能需要添加 id -> user、username -> user、email -> user 的缓存,此时就需要 @Caching 组合多个注解标签了。

常用属性

  • cacheable:组合多个 @Cacheable 注解

  • put:组合多个 @CachePut 注解

  • evict:组合多个 @CacheEvict 注解

    @CacheConfig(cacheNames = "users")
    public class CacheTestServiceImpl implements CacheTestService {
    /**
    * @Cacheable 的 cacheNames 默认为 "users"
    */
    @Cacheable(key="#id")
    public User getUser(Integer id) {...}
    }

7.自定义缓存过期时间

7.1 设置全局默认缓存过期时间:

复制代码
    // 提供默认的cacheManager,应用于全局,实现存活2天
    @Bean
    @Primary
    public CacheManager defaultCacheManager(
            RedisTemplate<?, ?> redisTemplate) {
        RedisCacheWriter writer = RedisCacheWriter.lockingRedisCacheWriter(redisTemplate.getConnectionFactory());
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofDays(2));
        return new RedisCacheManager(writer, config);
    }

7.2 定制部分缓存过期时间

  • 定制缓存过期时间,需要自定义RedisCacheManager来实现ttl设置。

  • 注意:项目中如已配置了RedisCacheManager需要在原配置的bean上添加注解 @Primary,以免造成干扰

    复制代码
      /**
      	自定义RedisCacheManager,用于在使用@Cacheable时设置ttl
       */
      @Bean
      public RedisCacheManager selfCacheManager(RedisTemplate<String, Object> redisTemplate) {
      	RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisTemplate.getConnectionFactory());
      	RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
      			.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getValueSerializer()));
      	return new SelfRedisCacheManager(redisCacheWriter, redisCacheConfiguration);
      }

SelfRedisCacheManager.java

复制代码
public class SelfRedisCacheManager extends RedisCacheManager {
    public SelfRedisCacheManager(RedisCacheWriter cacheWriter, RedisCacheConfiguration defaultCacheConfiguration) {
        super(cacheWriter, defaultCacheConfiguration);
    }

    @Override
    protected RedisCache createRedisCache(String name, RedisCacheConfiguration cacheConfig) {
        String[] cells = StringUtils.delimitedListToStringArray(name, "=");
        name = cells[0];
        if (cells.length > 1) {
            long ttl = Long.parseLong(cells[1]);
            // 根据传参设置缓存失效时间,默认单位是秒
            cacheConfig = cacheConfig.entryTtl(Duration.ofSeconds(ttl));
        }
        return super.createRedisCache(name, cacheConfig);
    }
}

使用:

复制代码
// value、cacheNames是等效的,ttl=600s,unless是不缓存的结果(为null时不缓存)
@Cacheable(value = "p_user=600",key = "#menu+'_'+#type+'_'+#userId",cacheManager = "selfCacheManager", unless = "#result == null")
public User getUser(...){
    xxx
}

// 当前方法执行时对应的key失效,也可以用@CachePut在当前方法执行时更新key
@CacheEvict(cacheNames = "p_user",key = "#p.menu+'_'+#p.type+'_'+#p.user")
public boolean setUser(User p){
    xxx
}

三、spEL表达式

参考地址:

1.@Cacheable设置过期时间:https://blog.csdn.net/weixin_41860719/article/details/125226096

相关推荐
Lu Yao_9 小时前
Redis 持久化
数据库·redis·缓存
June`9 小时前
Redis5安装与核心命令详解
数据库·redis·缓存
曾令胜11 小时前
excel导出使用arthas动态追踪方法调用耗时后性能优化的过程
spring·性能优化·excel
.格子衫.11 小时前
Spring Boot 原理篇
java·spring boot·后端
多云几多12 小时前
Yudao单体项目 springboot Admin安全验证开启
java·spring boot·spring·springbootadmin
摇滚侠13 小时前
Spring Boot 3零基础教程,Spring Intializer,笔记05
spring boot·笔记·spring
Jabes.yang14 小时前
Java求职面试实战:从Spring Boot到微服务架构的技术探讨
java·数据库·spring boot·微服务·面试·消息队列·互联网大厂
兮动人14 小时前
Spring Bean耗时分析工具
java·后端·spring·bean耗时分析工具
MESSIR2214 小时前
Spring IOC(控制反转)中常用注解
java·spring
摇滚侠15 小时前
Spring Boot 3零基础教程,Demo小结,笔记04
java·spring boot·笔记