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

相关推荐
华农第一蒟蒻2 分钟前
一次服务器CPU飙升的排查与解决
java·运维·服务器·spring boot·arthas
m0_7482299911 分钟前
帝国CMS后台搭建全攻略
java·c语言·开发语言·学习
码农娟33 分钟前
Hutool XML工具-XmlUtil的使用
xml·java
Geoking.39 分钟前
Redis 的 RDB 与 AOF:持久化机制全解析
数据库·redis·缓存
草青工作室40 分钟前
java-FreeMarker3.4自定义异常处理
java·前端·python
java1234_小锋1 小时前
Java中读写锁的应用场景是什么?
java·开发语言
闻哥1 小时前
从 AJAX 到浏览器渲染:前端底层原理与性能指标全解析
java·前端·spring boot·ajax·okhttp·面试
「QT(C++)开发工程师」1 小时前
C++ 多种单例模式
java·c++·单例模式
短剑重铸之日1 小时前
《SpringCloud实用版》统一认证授权:Spring Authorization Server + OAuth2 + JWT 生产级方案
java·后端·spring·jwt·oauth2
鱼跃鹰飞1 小时前
面试题:说一说redis和Memcached的区别
数据库·redis·memcached