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 清除。

相关推荐
咩咩啃树皮8 小时前
第40篇:Vue3组件化开发精讲——组件拆分、复用、父子通信、工程化架构
java·前端·架构
鱟鲥鳚8 小时前
Spring Boot 集成 LangChain4j:从模型调用到 Tool Calling(Demo版)
java·spring boot
大模型码小白10 小时前
【Python零基础教程】继承、多态与魔法函数:面向对象编程三大核心特性详解
java·大数据·开发语言·人工智能·python·ai编程
腾渊信息科技公司10 小时前
Spring Boot对接MES实战:视觉检测数据自动同步方案
java·人工智能·spring boot·后端·计算机视觉·ai·软件需求
爱笑的源码基地11 小时前
高并发 Redis 缓存门诊HIS系统源码,含财务统计药房进销存
java·程序·门诊系统·诊所系统·云诊所源码
wuqingshun31415911 小时前
TCP超时重传机制是为了解决什么问题?
java
二宝哥12 小时前
CentOS 7.9 系统下 Redis 5.0.4 单机安装与源码编译安装指南
redis·centos
莫逸风14 小时前
【AgentScope 2.0】 0. 学习指南
java·llm·agent·agentscope
z1234567898614 小时前
2026最新两款AI编程工具深度对比实测
java·数据库·ai编程
yaoxin52112315 小时前
470. Java 反射 - Member 接口与 AccessFlag
java·开发语言·python