引言
首先SpringCache 并非某一种 Cache 实现的技术,Spring Cache是Spring框架提供的一个模块,SpringCache 是一种缓存实现的通用技术,基于 Spring 提供的 Cache 框架,让开发者更容易将自己的缓存实现高效便捷的嵌入到自己的项目中。
它利用了AOP,实现了基于注解的缓存功能,并且进行了合理的抽象,业务代码不用关心底层是使用了什么缓存框架,只需要简单地加一个注解,就能实现缓存功能了。而且Spring Cache也提供了很多默认的配置,可以快速的上手使用缓存功能。
为什么使用Spring Cache
我们发现网上有各种缓存框架,各有各的优势,比如Redis、Memcached、Guava、Caffeine等等。
如果我们的程序想要使用缓存,就要与这些框架耦合。聪明的架构师已经在利用接口来降低耦合了,利用面向对象的抽象和多态的特性,做到业务代码与具体的框架分离。
但我们仍然需要显式地在代码中去调用与缓存有关的接口和方法,在合适的时候插入数据到缓存里,在合适的时候从缓存中读取数据。但如果使用spring Cache能给我们带来如下好处:
1)简化缓存管理:Spring Cache提供了一套简单且统一的API和注解,使得缓存的添加、更新、失效等操作变得更加方便和易于管理。
2)降低对底层缓存实现的依赖:Spring Cache的抽象层帮助开发人员摆脱对具体缓存实现的绑定,灵活地切换不同的缓存提供者而不需要改动业务代码。
3)支持多种缓存实现:Spring Cache兼容多种主流的缓存提供者,如Ehcache、Redis、Guava等,可以根据需求选择适合的缓存实现方式。
4)增强代码可读性:通过在方法上添加缓存注解,可以清晰地标识出哪些方法会使用缓存,提高代码的可读性和可维护性。
如何使用Spring Cache
spring cache的使用非常简单,主要三步骤:加依赖,开启缓存,加缓存注解。
导入相关依赖
在pom.xml文件中添加Spring Cache以及具体缓存实现(这里以Ehcache为例)的依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
配置Spring Cache
在Spring Boot应用中,可以通过在application.properties或application.yml中进行相关配置,如:
spring.cache.type=ehcache
编写Service类
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
@Service
public class MyDataService {
@Cacheable(value = "myDataCache", key = "#id")
public String getDataById(Long id) {
System.out.println("Fetching data from database for id: " + id);
return "Data" + id;
}
}
调用Service方法
MyDataService类中的getDataById方法通过@Cacheable注解指定了缓存的名称为myDataCache,并指定了缓存的key为方法的参数id。当调用该方法时,如果缓存中存在对应key的数据,将直接从缓存中取出返回;否则会执行方法内部逻辑,并将结果放入缓存中。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyDataController {
@Autowired
private MyDataService myDataService;
@GetMapping("/data/{id}")
public String getData(@PathVariable Long id) {
return myDataService.getDataById(id);
}
}
Spring Cache常用注解
Spring Cache提供了几个常用的注解,分别为@Cacheable、@CachePut、@CacheEvict、@Caching、 @CacheConfig。除了最后一个CacheConfig外,其余四个都可以用在类上或者方法级别上,如果用在类上,就是对该类的所有public方法生效,下面分别介绍一下这几个注解。
@Cacheable:
@Cacheble注解表示这个方法有了缓存的功能,方法的返回值会被缓存下来,下一次调用该方法前,会去检查是否缓存中已经有值,如果有就直接返回,不调用方法。如果没有,就调用方法,然后把结果缓存起来。这个注解一般用在查询方法上。
参数:
value :用来指定缓存组件的名字
key :缓存数据时使用的 key,可以用它来指定。默认是使用方法参数的值。(这个 key 你可以使用 spEL 表达式来编写)
keyGenerator :key 的生成器。 key 和 keyGenerator 二选一使用
cacheManager :可以用来指定缓存管理器。从哪个缓存管理器里面获取缓存。
condition :可以用来指定符合条件的情况下才缓存
unless :否定缓存。当 unless 指定的条件为 true ,方法的返回值就不会被缓存。当然你也可以获取到结果进行判断。(通过 #result 获取方法结果)
sync :是否使用异步模式。
@CachePut:
加了@CachePut注解的方法,会把方法的返回值put到缓存里面缓存起来,供其它地方使用。它通常用在新增方法上。
参数:
value:指定缓存的名称,表示数据将被存储在哪个缓存中。这个参数是必须要指定的。
key:指定缓存项的key,可以使用SpEL表达式来动态生成key。如果不指定,则默认使用方法的所有参数作为key。
condition:指定一个SpEL表达式,只有当条件为true时才会将返回值存储到缓存中。默认为空字符串,表示始终存储到缓存。
unless:指定一个SpEL表达式,当条件为true时不会将返回值存储到缓存中。通常用于排除特定情况下的缓存操作。
keyGenerator:指定自定义的KeyGenerator实现类,用于生成缓存key。
cacheManager:指定使用的缓存管理器的名称,用于从多个缓存管理器中选择特定的一个。
@CacheEvict
使用了CacheEvict注解的方法,会清空指定缓存。一般用在更新或者删除的方法上。
参数:
value:指定缓存的名称,表示要从哪个缓存中移除数据。这个参数是必须要指定的。
key:指定要移除的缓存项的key,可以使用SpEL表达式来动态生成key。如果不指定,则默认使用方法的所有参数作为key。
condition:指定一个SpEL表达式,只有当条件为true时才会执行缓存清除操作。默认为空字符串,表示始终清除缓存。
allEntries:指定是否移除缓存中所有的数据(默认为false)。设为true时将移除缓存中的所有数据,忽略key参数。
beforeInvocation:指定在方法执行之前还是之后执行缓存清除操作(默认为false)。设为true时,在方法执行之前就会清除缓存;设为false时,在方法执行成功后再清除缓存。
@Caching
Java注解的机制决定了,一个方法上只能有一个相同的注解生效。那有时候可能一个方法会操作多个缓存(这个在删除缓存操作中比较常见,在添加操作中不太常见)。
通过@Caching注解,开发者可以将多个缓存操作注解组合在一起,实现复杂的缓存逻辑。例如,在某个方法中可能既需要查询缓存又要更新缓存,或者需要在特定条件下清除缓存,这时可以使用@Caching注解来进行统一管理。这样可以减少重复代码、提高代码可读性,并灵活地控制缓存操作的行为。
参数:
cacheable:指定一个或多个@Cacheable注解,表示在方法执行前检查缓存中是否存在结果,并在缓存命中时直接返回缓存数据。
put:指定一个或多个@CachePut注解,表示无论缓存中是否存在相同key的数据,都会执行方法并更新缓存中对应的值。
evict:指定一个或多个@CacheEvict注解,表示从缓存中移除一个或多个缓存项。
Spring Cache集成Redis
导入相关依赖
从官方文档可以看到spring-boot-starter-data-redis 已经包含了jedis客户端,我们在使用jedis连接池的时候不必再添加jedis依赖。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
添加redis相关配置
server:
port: 8080
spring:
# redis相关配置
redis:
database: 0
host: localhost
port: 6379
password: 123456
jedis:
pool:
# 连接池最大连接数(使用负值表示没有限制)
max-active: 8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1ms
# 连接池中的最大空闲连接
max-idle: 8
# 连接池中的最小空闲连接
min-idle: 0
# 连接超时时间(毫秒)默认是2000ms
timeout: 2000ms
cache:
redis:
## Entry expiration in milliseconds. By default the entries never expire.
time-to-live: 1d
#写入redis时是否使用键前缀。
use-key-prefix: true
启用缓存功能
在Spring Boot的主应用程序类上添加@EnableCaching注解,启用缓存功能。
编写Service类
创建一个Service类,定义一个简单的方法进行数据查询,并添加缓存注解使用Redis作为缓存提供者
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
@Service
public class MyDataService {
@Cacheable(value = "myDataCache", key = "#id")
public String getDataById(Long id) {
System.out.println("Fetching data from database for id: " + id);
return "Data" + id;
}
}
示例Controller类: 创建一个Controller类,调用Service方法获取数据。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyDataController {
@Autowired
private MyDataService myDataService;
@GetMapping("/data/{id}")
public String getData(@PathVariable Long id) {
return myDataService.getDataById(id);
}
}
总结
Spring Cache是Spring框架提供的缓存抽象层,用于简化应用中对缓存的管理。通过使用Spring Cache,开发者可以轻松地将缓存集成到应用程序中,提高性能、降低数据库负载,并优化系统的响应时间,但也存在以下不足:
- 不支持TTL,不能为每个 key 设置单独过期时间 expires time,
- 针对多线程没有专门的处理,所以当多线程时,是会产生数据不一致性的。(同样,一般有高并发操作的缓存数据,都会特殊处理,而不太使用这种方式)
本文暂时没有评论,来添加一个吧(●'◡'●)