Spring对于Cache的抽象架构
概念/注解 | 作用 |
---|---|
Cache | 缓存接口,定义缓存操作。实现有:RedisCache、EhCacheCache、 ConcurrentMapCache等 |
CacheManager | 缓存管理器,管理各种缓存(Cache)组件 |
@Cacheable | 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存 |
@CacheEvict | 清空缓存 |
@CachePut | 保证方法被调用,又希望结果被缓存。 |
@EnableCaching | 开启基于注解的缓存 |
keyGenerator | 缓存数据时key生成策略 |
serialize | 缓存数据时value序列化策略 |
使用方法就是在启动类上加上@EnableCaching
注解来开启缓存功能。之后就可以在方法上使用上述注解进行缓存的使用下面,我们针对几个重要注解做一下讲解。
@Cacheable
@Cacheable
:将方法运行的结果进行缓存,以后再获取相同的数据时,直接从缓存中获取,不再调用方法。使用示例如下:
@Cacheable(cacheNames = {"emp"})
public Employee getEmpById(Integer id){
Employee emp = employeeMapper.getEmpById(id);
return emp;
}
@Cacheable
注解的属性:
属性名 | 描述 |
---|---|
cacheNames/value | 指定缓存的名字,缓存使用CacheManager管理多个缓存组件Cache,这些Cache组件就是根据这个名字进行区分的。对缓存的真正CRUD操作在Cache中定义,每个缓存组件Cache都有自己唯一的名字,通过cacheNames或者value属性指定,相当于是将缓存的键值对进行分组,缓存的名字是一个数组,也就是说可以将一个缓存键值对分到多个组里面 |
key | 缓存数据时的key的值,默认是使用方法参数的值,可以使用SpEL表达式计算key的值 |
keyGenerator | 缓存的生成策略,和key二选一,都是生成键的,keyGenerator可自定义 |
cacheManager | 指定缓存管理器(如ConcurrentHashMap、Redis等) |
cacheResolver | 和cacheManager功能一样,和cacheManager二选一 |
condition | 指定缓存的条件(满足什么条件时才缓存),可用SpEL表达式(如id>0,表示当入参id大于0时才缓存) |
unless | 否定缓存,即满足unless指定的条件时,方法的结果不进行缓存,使用unless时可以在调用的方法获取到结果之后再进行判断(如result==null,表示如果结果为null时不缓存) |
sync | 是否使用异步模式进行缓存 |
注意:
-
既满足condition又满足unless条件的也不进行缓存
-
使用异步模式进行缓存时(sync=true):unless条件将不被支持
可用的SpEL表达式见下表:
名字 | 位置 | 描述 | 示例 |
---|---|---|---|
methodName | root object | 当前被调用的方法名 | #root.methodName |
method | root object | 当前被调用的方法 | #root.method.name |
target | root object | 当前被调用的目标对象 | root.target |
targetClass | root object | 当前被调用的目标对象类 | #root.targetClass |
args | root object | 当前被调用的方法的参数列表 | #root.args[0] |
caches | root object | 当前方法调用使用的存列表 | (如@Cacheable(value= {“cache1”, “cache2”})),则有两 个cache root.caches[0].name |
argument name | evaluation context | 方法参数的名字,可以直接 #参数名,也可以使用#p0或#a0的形式,0代表参数的索引 | #iban、#a0、#p0 |
result | evaluation context | 方法执行后的返回值(仅当方法 执行之后的判断有效,如"unless","cache put"的表达式,"cache evict"的表达式beforeInvocation=false) | #result |
@CachePut
说明:既调用方法,又更新缓存数据,一般用于更新操作,在更新缓存时一定要和想更新的缓存有相同的缓存名称和相同的key( 可类比同一张表的同一条数据)。示例如下:
@CachePut(value = "emp",key = "#employee.id")
public Employee updateEmp(Employee employee){
employeeMapper.updateEmp(employee);
return employee;
}
@CacheEvict
说明:缓存清除,清除缓存时要指明缓存的名字和key,相当于告诉数据库要删除哪个表中的哪条数据,key默认为参数的值。
注意:allEntries属性是指是否清除指定缓存中的所有键值对,默认为false,设置为true时会清除缓存中 的所有键值对,与key属性二选一使用。beforeInvocation 指在@CacheEvict注解的方法调用之前清除指定缓存,默认为false,即在方法调用之后清除缓存。设置为true时则会在方法调用之前清除缓存( 在方法调用之前还是之后清除缓存的区别在于方法调用时是否会出现异常,若不出现异常,这两种设置没有区别,若出现异常,设置为在方法调用之后清除缓存将不起作用,因为方法调用失败了) 。
示例:
@CacheEvict(value = "emp",key = "#id",beforeInvocation = true)
public void delEmp(Integer id){
employeeMapper.deleteEmpById(id);
}
@CacheConfig
作用:标注在类上,抽取缓存相关注解的公共配置,可抽取的公共配置有缓存名字、主键生成器等(如注解中的属性所示):
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CacheConfig {
String[] cacheNames() default {};
String keyGenerator() default "";
String cacheManager() default "";
String cacheResolver() default "";
}
示例:通过@CacheConfig的cacheNames 属性指定缓存的名字之后,该类中的其他缓存注解就不必再写value或者cacheName了,会使用该名字作为value或cacheName的值,当然也遵循就近原则:
@Service
@CacheConfig(cacheNames = "emp")
public class EmployeeService {
@Autowired
EmployeeMapper employeeMapper;
@Cacheable
public Employee getEmpById(Integer id) {
Employee emp = employeeMapper.getEmpById(id);
return emp;
}
@CachePut(key = "#employee.id")
public Employee updateEmp(Employee employee) {
employeeMapper.updateEmp(employee);
return employee;
}
@CacheEvict(key = "#id", beforeInvocation = true)
public void delEmp(Integer id) {
employeeMapper.deleteEmpById(id);
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库