在这里插入图片描述

介绍

Spring Cache 是 Spring 框架提供的缓存抽象层,它简化了在应用中添加缓存功能的过程,允许开发者通过注解方式轻松实现缓存逻辑,而无需关注具体的缓存实现细节。

  1. 缓存抽象:Spring Cache 不直接提供缓存实现,而是定义了一套接口(如 CacheCacheManager),支持多种缓存实现(如 Caffeine、EhCache、Redis 等)。
  2. 注解驱动:通过注解(如 @Cacheable@CachePut@CacheEvict)声明缓存规则,无需手动编写缓存逻辑。
  3. 透明集成:缓存操作与业务逻辑解耦,开发者只需关注业务代码。

常用注解

在这里插入图片描述

  1. @Cacheable
    标记方法结果可被缓存。调用方法时,先检查缓存:

    • 若缓存存在,直接返回缓存值,不执行方法。
    • 若缓存不存在,执行方法并将结果存入缓存。
    @Cacheable(value = "users", key = "#id")
    public User getUserById(Long id) {
        // 从数据库查询用户
        return userRepository.findById(id);
    }
    
  2. @CachePut
    保证方法执行,并将结果更新到缓存(常用于更新操作)。

    @CachePut(value = "users", key = "#user.id")
    public User updateUser(User user) {
        return userRepository.save(user);
    }
    
  3. @CacheEvict
    移除缓存条目(常用于删除操作)。

    @CacheEvict(value = "users", key = "#id")
    public void deleteUser(Long id) {
        userRepository.deleteById(id);
    }
    
  4. @Caching
    组合多个缓存注解(如同时更新和删除缓存)。

    @Caching(
        put = @CachePut(value = "users", key = "#user.id"),
        evict = @CacheEvict(value = "userList", allEntries = true)
    )
    public User saveUser(User user) {
        return userRepository.save(user);
    }
    
  5. @CacheConfig
    在类级别统一配置缓存属性(如 valuekeyGenerator),简化方法上的注解。

@CacheConfig(cacheNames = "users")
public class UserService {
  
  @Cacheable(key = "#id")  // 无需再指定value
  public User getUserById(Long id) { ... }
  
  @CachePut(key = "#user.id")
  public User updateUser(User user) { ... }
}

实现步骤

  • 1.添加依赖(Maven):
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
  • 2.开启缓存支持
    在启动类添加 @EnableCaching 注解。
@SpringBootApplication
@EnableTransactionManagement //开启注解方式的事务管理
@Slf4j
@EnableCaching//开启缓存功能
public class SkyApplication {
    public static void main(String[] args) {
        SpringApplication.run(SkyApplication.class, args);
        log.info("server started");
    }
}
  • 3.配置缓存实现

在 yml中配置Redis
在这里插入图片描述
在这里插入图片描述

  • 4.注解声明缓存规则

如:c端

    /**
     * 条件查询
     *
     * @param categoryId
     * @return
     */
    @GetMapping("/list")
    @ApiOperation("根据分类id查询套餐")
    @Cacheable(cacheNames = "setmealCache",key = "#categoryId")//key: setmealCache::categoryId
    public Result<List<Setmeal>> list(Long categoryId) {
        Setmeal setmeal = new Setmeal();
        setmeal.setCategoryId(categoryId);
        setmeal.setStatus(StatusConstant.ENABLE);

        List<Setmeal> list = setmealService.list(setmeal);
        return Result.success(list);
    }

管理端

    /**
     * 新增套餐
     * @param setmealDTO
     * @return
     */
    @PostMapping
    @ApiOperation("新增套餐")
    @CacheEvict(cacheNames = "setmealCache",key = "#setmealDTO.categoryId")
    public Result save(@RequestBody SetmealDTO setmealDTO){
        log.info("新增套餐:{}",setmealDTO);
        setmealService.saveWithDish(setmealDTO);
        return Result.success();
    }

    /**
     * 删除套餐
     * @param ids
     * @return
     */
    @DeleteMapping
    @ApiOperation("批量删除套餐")
    @CacheEvict(cacheNames = "setmealCache",allEntries = true)
    public Result delete(@RequestParam List<Long> ids){
        log.info("批量删除套餐:{}",ids);
        setmealService.deleteBatch(ids);
        return Result.success();
    }

    /**
     * 修改套餐起售停售状态
     * @param status
     * @param id
     * @return
     */
    @PostMapping("/status/{status}")
    @ApiOperation("修改套餐起售停售状态")
    @CacheEvict(cacheNames = "setmealCache",allEntries = true)
    public Result startOrStop(@PathVariable("status") Integer status, Long id){
        log.info("套餐起售或停售:{}",id);
        setmealService.startOrStop(status,id);
        return Result.success();
    }
  • 5.确保解耦

通过上述注解方式,缓存规则(如缓存名称、缓存键、缓存更新 / 删除时机等)通过注解声明在方法上,与业务逻辑(查询、保存、删除用户的具体实现)分离,新增或修改缓存策略时,无需改动业务逻辑代码,只需调整注解参数即可,实现了缓存规则和业务逻辑的解耦。

这样就利用 Spring Cache 抽象层,以注解驱动的方式实现了高效缓存策略,让缓存操作与业务逻辑清晰分离。

注意事项

  • 缓存键生成:默认使用方法参数生成键,可通过 key 属性自定义(SpEL 表达式),或配置 KeyGenerator
  • 缓存穿透:可通过空值缓存(@Cacheable(unless = "#result == null"))避免。
  • 缓存更新:使用 @CachePut 确保缓存与数据源一致性,避免直接修改缓存。
  • 分布式缓存:在分布式系统中,推荐使用 Redis 等集中式缓存,避免本地缓存(如 Caffeine)的一致性问题。
Logo

助力广东及东莞地区开发者,代码托管、在线学习与竞赛、技术交流与分享、资源共享、职业发展,成为松山湖开发者首选的工作与学习平台

更多推荐