深入理解 Spring Cache 及其核心注解
一、Spring Cache 概述
Spring Cache 并不是一个具体的缓存实现方案,而是一套抽象的缓存规范。它支持多种缓存技术,如 Ehcache、Redis、Caffeine 等,开发者可以根据项目需求灵活选择合适的缓存技术。其核心思想是通过在方法上添加注解,在方法调用前后自动完成缓存的操作,例如查询数据时优先从缓存中获取,数据更新时同步更新缓存,从而避免重复执行方法和数据库查询,提升系统性能和响应速度。
Spring Cache 的工作流程大致如下:当被缓存注解标注的方法被调用时,Spring Cache 会先检查缓存中是否存在对应的数据。如果存在,直接从缓存中返回数据,不再执行方法体;如果不存在,则执行方法体,获取数据,并将数据存入缓存,以便下次使用。这种 “先查缓存,后执行方法” 的机制,大大减少了数据库的负载和方法的执行次数。
相关Maven坐标
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId>
</dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope>
</dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.0</version>
</dependency>
二、@EnableCaching 注解
@EnableCaching 是开启 Spring Cache 功能的关键注解,通常被添加到 Spring Boot 项目的配置类上,用于启用缓存功能。只有在配置类上添加了该注解,Spring 才会识别并处理其他缓存相关的注解。
添加 @EnableCaching 注解后,Spring 会自动扫描项目中带有缓存注解的方法,并在方法调用时,按照缓存规则进行相应的缓存操作。它就像是一把钥匙,开启了 Spring 框架中缓存功能的大门,让开发者能够使用各种缓存注解来简化开发过程。
三、@Cacheable 注解
@Cacheable 是 Spring Cache 中最常用的注解之一,它主要用于标注查询方法。当方法被标注 @Cacheable 后,Spring 在调用该方法时,会首先检查指定的缓存中是否存在对应的数据。如果存在,直接从缓存中返回数据,不再执行方法体;如果不存在,则执行方法体获取数据,并将数据存入缓存,以便后续使用。
@GetMapping//在方法执行前,先查询缓存,若没有执行方法,并且把数据放入缓存//若查到了,会去代理方法内执行,就不会执行原方法@Cacheable(cacheNames = "userCache",key = "#id")public User getById(Long id){User user = userMapper.getById(id);return user;}
在上述代码中,@Cacheable 注解的 value 属性指定了缓存的名称(这里是 users),key 属性定义了缓存的键(这里使用方法参数 id 作为键)。这意味着,每次调用 getUserById 方法时,Spring 会根据 id 值在 users 缓存中查找数据。如果找到,直接返回;找不到则执行方法从数据库查询,并将结果存入缓存。通过 @Cacheable 注解,我们可以轻松实现查询方法的缓存功能,减少数据库的压力。
四、@CachePut 注解
@CachePut 注解用于更新缓存数据。与 @Cacheable 不同,@CachePut 无论缓存中是否存在数据,都会先执行方法体,获取最新的数据,然后将数据更新到缓存中。这一特性使得 @CachePut 非常适合用于数据更新的场景,例如修改用户信息后,及时将最新的用户数据更新到缓存中。
@PostMapping//把方法的返回值放到缓存当中//key为userCache::user的id//这里方法开始执行时,user内并没有id key也不会生成,等数据库插入好数据,并且id赋值给User才//开始构造key 再把数据放入缓存中@CachePut(cacheNames = "userCache",key = "#user.id")
// @CachePut(cacheNames = "userCache",key = "#result.id") //返回值的id
// @CachePut(cacheNames = "userCache",key = "#p0.id") //第一个参数的id
// @CachePut(cacheNames = "userCache",key = "#a0.id") //第一个参数的id
// @CachePut(cacheNames = "userCache",key = "#root.args[0].id") //第一个参数的idpublic User save(@RequestBody User user){userMapper.insert(user);return user;}
在上述示例中,当调用 updateUser 方法更新用户信息时,方法执行完成后,返回的最新用户数据会被存入 users 缓存中,键为用户的 id。这样,后续查询该用户信息时,就能从缓存中获取到最新的数据,保证了缓存数据与数据库数据的一致性。
五、@CacheEvict 注解
@CacheEvict 注解用于从缓存中删除数据。当方法被标注 @CacheEvict 后,在方法执行完成时,Spring 会根据注解配置,从指定的缓存中删除相应的数据。它主要用于数据删除、修改等导致缓存数据失效的场景,以确保缓存中不会存在过期或无效的数据。
@DeleteMapping//方法执行后,删除指定缓存@CacheEvict(cacheNames = "userCache",key = "#id",beforeInvocation=true)public void deleteById(Long id){userMapper.deleteById(id);}@DeleteMapping("/delAll")//方法执行后,删除在userCache下的全部缓存@CacheEvict(cacheNames = "userCache",allEntries = true,beforeInvocation=true)public void deleteAll(){userMapper.deleteAll();}
在上述代码中,当调用 deleteUser 方法删除用户时,方法执行完成后,Spring 会从 users 缓存中删除键为 id 的数据。此外,@CacheEvict 还支持一些其他属性,如 allEntries = true,用于清空整个缓存;beforeInvocation = true,用于在方法执行前就删除缓存,即使方法执行过程中抛出异常,缓存也会被删除。