Spring Cache 实战:核心注解详解与缓存过期时间配置

RedisTemplate 是 Spring Data Redis 提供的一个核心类,封装了大量与 Redis 交互的操作方法,使用灵活、功能强大。而 Spring Cache 则是在更高抽象层上提供的一套缓存编程模型------它通过注解的方式简化缓存的使用,开发者无需直接操作 RedisTemplate 或其他底层缓存客户端,即可实现对缓存的读写与管理。

Spring Cache 并不仅限于 Redis。它是一个通用的缓存抽象层,支持多种缓存实现,例如 Ehcache、Caffeine、ConcurrentHashMap(基于内存)等。这意味着我们可以在不修改业务代码的前提下,轻松切换底层缓存存储方案。即使不配置任何外部缓存组件,Spring Cache 也能自动回退到基于内存的简单缓存实现,确保功能正常运行。

Spring Cache 中常用的几个核心注解包括:

  • @EnableCaching:添加在 Spring Boot 启动类(或配置类)上,用于启用基于注解的缓存功能。
  • @Cacheable:通常用于查询方法。当方法被调用时,Spring 会先尝试从缓存中查找对应的数据;如果命中,则直接返回缓存结果,避免执行方法体;若未命中,则执行方法,并将返回值存入缓存供后续使用。
  • @CacheEvict:常用于新增、修改或删除操作的方法上,用于清除缓存中的一条或多条数据,确保缓存与数据源的一致性。
  • @CachePut:用于更新缓存。无论缓存是否存在,都会执行方法体,并将返回值写入缓存。适用于需要强制刷新缓存的场景。

1. 使用

1. @EnableCaching:启用缓存支持

要使用 Spring Cache 的注解功能,首先需要在 Spring Boot 的主启动类(或配置类)上添加 @EnableCaching 注解,以开启基于注解的缓存管理:

java 复制代码
@SpringBootApplication
@EnableCaching // 启用 Spring Cache 注解功能
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

该注解会触发 Spring 自动配置缓存相关的基础设施(如 CacheManager),从而支持后续的 @Cacheable、@CachePut 和 @CacheEvict 等注解。

2. @CachePut:更新或写入缓存

@CachePut 用于将方法的返回值写入缓存,无论缓存中是否已存在对应数据,方法体都会执行。常用于新增或更新操作后同步刷新缓存。

关键属性说明:

  • value:指定缓存的"命名空间"(即缓存名称),相当于一个缓存区域。
  • key:在该命名空间下唯一的缓存键。支持 Spring 表达式语言(SpEL),例如 #user.id 表示方法参数 user 的 id 属性,#result.id 表示方法返回对象的 id 属性。
java 复制代码
@PostMapping("/user")
@CachePut(value = "userCache", key = "#result.id")
public User save(@RequestBody User user) {
    userMapper.insert(user); // 假设插入后 user 对象包含生成的 ID
    return user;
}

注意:@CachePut不会跳过方法执行,因此适用于需要强制更新缓存的场景。

3. @Cacheable:读取缓存(若存在)

@Cacheable 通常用于查询方法。Spring 会在方法调用前先检查缓存:

  • 如果命中(缓存中有对应 key 的数据),则直接返回缓存结果,不执行方法体;
  • 如果未命中,则执行方法,并将返回值自动存入缓存。
java 复制代码
@GetMapping("/user/{id}")
@Cacheable(value = "userCache", key = "#id")
public User findById(@PathVariable Long id) {
    return userMapper.getById(id); // 仅当缓存未命中时才会执行此行
}

这是提升查询性能最常用的注解,能有效减少数据库访问。

4. @CacheEvict:清除缓存

@CacheEvict 用于在方法执行后删除缓存中的数据,确保缓存与数据源的一致性。常用于删除或更新操作。

删除单条缓存:
java 复制代码
@DeleteMapping("/user/{id}")
@CacheEvict(value = "userCache", key = "#id")
public void deleteById(@PathVariable Long id) {
    userMapper.deleteById(id);
}
清空整个缓存区域:

通过设置 allEntries = true,可一次性清除 value 指定缓存区域中的所有条目:

java 复制代码
@DeleteMapping("/user")
@CacheEvict(value = "userCache", allEntries = true)
public void deleteAll() {
    userMapper.deleteAll();
}

注意:allEntries = true 会忽略 key 属性,直接清空整个缓存命名空间。

2. 设置缓存时间

默认情况下,使用 @Cacheable 或 @CachePut 注解写入 Redis 的缓存数据没有过期时间(TTL),会一直保留在缓存中。在实际项目中,为了避免缓存数据长期不更新或占用过多内存,通常需要为缓存设置合理的过期时间。

Spring Cache 通过 cacheManager 属性指定使用的缓存管理器(CacheManager),而不同的 CacheManager 实现可以配置不同的缓存策略,包括过期时间。对于 Redis,我们可以通过自定义 RedisCacheManager 来实现这一需求。

1. 创建配置类

首先,创建一个 Spring 配置类,注册一个带有 TTL(Time-To-Live)策略的 RedisCacheManager Bean:

java 复制代码
@Configuration
public class SpringCacheConfig {

    /**
     * 定义一个缓存管理器,所有使用该管理器的缓存项默认 30 分钟后过期
     */
    @Bean("cacheManager30Minutes")
    public RedisCacheManager cacheManager30Minutes(RedisConnectionFactory connectionFactory) {
        // 配置默认的缓存设置:设置 TTL 为 30 分钟
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofMinutes(30)) // 设置缓存过期时间为 30 分钟
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(RedisSerializer.string()))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(RedisSerializer.json()));

        return RedisCacheManager.builder(connectionFactory)
                .cacheDefaults(config)
                .transactionAware() // 支持事务(可选)
                .build();
    }
}

说明:

@Bean("cacheManager30Minutes") 中的名称 "cacheManager30Minutes" 将作为该缓存管理器的唯一标识。

如果你使用的是较新版本的 Spring Boot(2.7+),建议显式指定序列化方式(如 JSON),避免默认 JDK 序列化带来的兼容性问题。

2. 设置TTL

接下来,在需要设置过期时间的缓存方法上,通过 cacheManager 属性引用我们刚刚定义的 Bean:

java 复制代码
@GetMapping("/user/{id}")
@Cacheable(
    value = "userCache",
    key = "#id",
    cacheManager = "cacheManager30Minutes" // 指定使用 30 分钟过期的缓存管理器
)
public User findById(@PathVariable Long id) {
    return userMapper.getById(id);
}

这样,所有通过该方法写入 userCache 的缓存数据,都会在 30 分钟后自动过期并被 Redis 清除。

相关推荐
@淡 定6 小时前
Redis热点Key独立集群实现方案
数据库·redis·缓存
野生的码农6 小时前
码农的妇产科实习记录
android·java·人工智能
吳所畏惧6 小时前
Linux环境/麒麟V10SP3下离线安装Redis、修改默认密码并设置Redis开机自启动
linux·运维·服务器·redis·中间件·架构·ssh
毕设源码-赖学姐7 小时前
【开题答辩全过程】以 高校人才培养方案管理系统的设计与实现为例,包含答辩的问题和答案
java
一起努力啊~7 小时前
算法刷题-二分查找
java·数据结构·算法
小途软件7 小时前
高校宿舍访客预约管理平台开发
java·人工智能·pytorch·python·深度学习·语言模型
J_liaty7 小时前
Java版本演进:从JDK 8到JDK 21的特性革命与对比分析
java·开发语言·jdk
+VX:Fegn08957 小时前
计算机毕业设计|基于springboot + vue律师咨询系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·课程设计
daidaidaiyu8 小时前
一文学习和实践 当下互联网安全的基石 - TLS 和 SSL
java·netty
hssfscv8 小时前
Javaweb学习笔记——后端实战2_部门管理
java·笔记·学习