一、Spring Cache 核心概念

Spring Cache 是 Spring 框架提供的缓存抽象层,它不直接实现缓存,而是定义了一套统一的缓存操作接口,底层可以对接不同的缓存实现(如 Redis、Caffeine、Ehcache 等)。核心优势是:

  • 基于注解,无需手写缓存逻辑,代码侵入性极低;
  • 统一的 API,切换缓存实现只需改配置,无需改业务代码;
  • 支持缓存的增、删、更新、失效等全生命周期管理。
核心注解
注解作用
@EnableCaching开启缓存功能(必须加在配置类 / 启动类上)
@Cacheable方法执行前先查缓存,有则返回缓存值,无则执行方法并将结果存入缓存
@CachePut执行方法后将结果存入缓存(常用于更新操作,不会跳过方法执行)
@CacheEvict移除缓存(常用于删除操作)
@Caching组合多个缓存注解(如同时更新 + 删除)
@CacheConfig类级别注解,统一配置缓存名称、keyGenerator 等,简化方法级注解配置

二、快速上手:Spring Cache + Redis 实战

以最常用的 Redis 作为缓存实现,演示完整使用流程。

1. 前置依赖(Maven)
<!-- Spring Cache 核心依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!-- Redis 依赖(缓存实现) -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 可选:Jackson 序列化,解决 Redis 存储对象乱码问题 -->
<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
2. 配置 Redis 与缓存(application.yml)
spring:
  # Redis 配置
  redis:
    host: localhost
    port: 6379
    password: 123456 # 无密码则省略
    database: 0
  # 缓存配置
  cache:
    type: redis # 指定缓存类型为 Redis
    redis:
      time-to-live: 3600000 # 缓存过期时间(毫秒),1小时
      key-prefix: "user:" # 缓存key前缀,方便区分
      use-key-prefix: true # 启用前缀
3. 开启缓存(启动类)
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

@SpringBootApplication
@EnableCaching // 必须开启缓存注解功能
public class CacheDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(CacheDemoApplication.class, args);
    }
}
4. 业务代码中使用缓存

以用户查询、更新、删除为例:

import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    // 模拟数据库存储
    private Map<Long, User> userMap = new HashMap<>();

    /**
     * 查询用户:优先查缓存,无则查"数据库"并缓存
     * @param id 用户ID
     * @return 用户信息
     */
    @Cacheable(value = "userCache", key = "#id") 
    // value:缓存名称(必填);key:缓存键(SpEL表达式,#id表示方法参数id)
    public User getUserById(Long id) {
        //先查缓存,无则查"数据库"并缓存,打印下面语句,如果缓存存在则不会执行下面打印语句
        System.out.println("执行数据库查询,并缓存,id=" + id); // 用于验证是否走缓存
        return userMap.get(id);
    }

    /**
     * 更新用户:执行方法后更新缓存(方法一定会执行)
     * @param user 更新后的用户信息
     * @return 更新后的用户
     */
    @CachePut(value = "userCache", key = "#user.id")
    public User updateUser(User user) {
        System.out.println("执行数据库更新,id=" + user.getId());
        userMap.put(user.getId(), user);
        return user;
    }

    /**
     * 删除用户:移除对应缓存
     * @param id 用户ID
     */
    @CacheEvict(value = "userCache", key = "#id")
    public void deleteUser(Long id) {
        System.out.println("执行数据库删除,id=" + id);
        userMap.remove(id);
    }

    // 模拟用户实体类
    public static class User {
        private Long id;
        private String name;
        private Integer age;

        // 省略getter/setter/构造方法
    }
}
5. 测试验证
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class CacheTest {

    @Autowired
    private UserService userService;

    @Test
    public void testCache() {
        // 1. 首次查询:无缓存,执行数据库查询
        User user1 = userService.getUserById(1L);
        // 2. 二次查询:有缓存,不执行数据库查询
        User user2 = userService.getUserById(1L);
        // 3. 更新用户:执行方法并更新缓存
        User updateUser = new User(1L, "张三", 25);
        userService.updateUser(updateUser);
        // 4. 删除用户:移除缓存
        userService.deleteUser(1L);
    }
}

三、关键细节说明

  1. SpEL 表达式(缓存 key):
    • #id:方法参数 id;
    • #user.id:方法参数 user 的 id 属性;
    • #root.methodName:当前方法名;
    • #root.args[0]:方法第一个参数。
  2. 缓存失效场景:
    • 手动调用 @CacheEvict;
    • 缓存达到过期时间(如配置的 1 小时);
    • 底层缓存实现自身的清理策略(如 Redis 内存淘汰)。
  3. 自定义缓存配置:如果需要自定义 Redis 序列化(解决对象乱码),可添加配置类:
    import org.springframework.cache.annotation.EnableCaching;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.data.redis.cache.RedisCacheConfiguration;
    import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
    import org.springframework.data.redis.serializer.RedisSerializationContext;
    import org.springframework.data.redis.serializer.StringRedisSerializer;
    
    @Configuration
    @EnableCaching
    public class CacheConfig {
        @Bean
        public RedisCacheConfiguration redisCacheConfiguration() {
            return RedisCacheConfiguration.defaultCacheConfig()
                    // key 序列化
                    .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
                    // value 序列化(JSON格式)
                    .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()))
                    .entryTtl(java.time.Duration.ofHours(1)); // 过期时间
        }
    }
    

总结

  1. 核心定位:Spring Cache 是缓存抽象层,通过注解简化缓存逻辑,底层可对接 Redis/Caffeine 等实现;
  2. 核心注解:@EnableCaching 开启缓存,@Cacheable 查缓存,@CachePut 更新缓存,@CacheEvict 删除缓存;
  3. 关键配置:使用 Redis 时需配置序列化方式(避免乱码)和过期时间,保证缓存数据的有效性和可读性。
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐