一、简介
- 缓存介绍
- Spring 从 3.1 开始就引入了对 Cache 的支持。定义了 org.springframework.cache.Cache 和 org.springframework.cache.CacheManager 接口来统一不同的缓存技术。并支持使用 JCache(JSR-107)注解简化我们的开发。
- 其使用方法和原理都类似于 Spring 对事务管理的支持。Spring Cache 是作用在方法上的,其核心思想是,当我们在调用一个缓存方法时会把该方法参数和返回结果作为一个键值对存在缓存中。
- Cache 和 CacheManager 接口说明
- Cache 接口包含缓存的各种操作集合,你操作缓存就是通过这个接口来操作的。
- Cache 接口下 Spring 提供了各种 xxxCache 的实现,比如:RedisCache、EhCache、ConcurrentMapCache
- CacheManager 定义了创建、配置、获取、管理和控制多个唯一命名的 Cache。这些 Cache 存在于 CacheManager 的上下文中。
小结
每次调用需要缓存功能的方法时,Spring 会检查指定参数的指定目标方法是否已经被调用过,如果有就直接从缓存中获取方法调用后的结果,如果没有就调用方法并缓存结果后返回给用户。下次调用直接从缓存中获取
注意:本类里调用时会失效
因为@Cacheable等注解实现的功能是通过AOP完成的。
二、@Cacheable 注解使用详细介绍
1、缓存使用步骤
@Cacheable
这个注解,用它就是为了使用缓存的。所以我们可以先说一下缓存的使用步骤
1、开启基于注解的缓存,使用
@EnableCaching
标识在 SpringBoot 的主启动类上。2、标注缓存注解即可
① 第一步:开启基于注解的缓存,使用 @EnableCaching
标注在 springboot 主启动类上
@SpringBootApplication
@EnableCaching
public class SpringbootApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootApplication.class, args);
}
}
② 第二步:标注缓存注解
// #id的值作为缓存中的key
@Cacheable(cacheNames = "getData", key = "#id")
public String getData(Integer id) {
System.out.println("查询:" + id);
return "查询结果";
}
注:这里使用 @Cacheable
注解就可以将运行结果缓存,以后查询相同的数据,直接从缓存中取,返回缓存数据,方法中的代码将不会再执行
2、常用属性说明
下面介绍一下 @Cacheable
这个注解常用的几个属性:
cacheNames/value
:用来指定缓存组件的名字key
:缓存数据时使用的 key,可以用它来指定。默认是使用方法参数的值。(这个 key 你可以使用 spEL 表达式来编写)keyGenerator
:key 的生成器。 key 和 keyGenerator 二选一使用cacheManager
:可以用来指定缓存管理器。从哪个缓存管理器里面获取缓存。condition
:可以用来指定符合条件的情况下才缓存unless
:否定缓存。当 unless 指定的条件为 true ,方法的返回值就不会被缓存。当然你也可以获取到结果进行判断。(通过#result
获取方法结果)sync
:是否使用异步模式。
① cacheNames
用来指定缓存组件的名字,将方法的返回结果放在哪个缓存中,可以是数组的方式,支持指定多个缓存。
@Cacheable(cacheNames = {"getData1","getData2"})
public String getData(Integer id) {
System.out.println("查询:" + id);
return "查询结果";
}
② key
缓存数据时使用的 key。默认使用的是方法参数的值。可以使用 spEL 表达式去编写。
// 设置key为getData[2]
@Cacheable(cacheNames = "getData", key = "#root.methodName + '[' + #id + ']'")
public String getData(Integer id) {
System.out.println("查询:" + id);
return "查询结果";
}
③ keyGenerator
key 的生成器,可以自己指定 key 的生成器,通过这个生成器来生成 key。
/**
* 自定义,按照自己的生成逻辑生成key
* @return
*/
@Bean("myKeyGenerator")
public KeyGenerator keyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object target, Method method, Object... params) {
return method.getName() + "[" + Arrays.asList(params).toString() + "]";
}
};
}
// 使用自己自定义的keyGenerator:myKeyGenerator
@Cacheable(cacheNames = "getData", keyGenerator = "myKeyGenerator")
public String getData(Integer id) {
System.out.println("查询:" + id);
return "查询结果";
}
key 和 keyGenerator 使用的时候,一般二选一。
④ condition
符合条件的情况下才缓存。方法返回的数据要不要缓存,可以做一个动态判断。
// id 大于 100 时才会被缓存
@Cacheable(cacheNames = "name1", condition = "#id > 100")
public String getData(Integer id) {
System.out.println("查询:" + id);
return "查询结果";
}
⑤ unless
否定缓存。当 unless 指定的条件为 true ,方法的返回值就不会被缓存。
// id 大于 100 时就不会被缓存
@Cacheable(cacheNames = "getData", unless = "#id > 100")
public String getData(Integer id) {
System.out.println("查询:" + id);
return "查询结果";
}
⑥ sync
是否使用异步模式。默认是方法执行完,以同步的方式将方法返回的结果存在缓存中。
3、spEL 编写 key
缓存的 key 支持使用 spEL 表达式去编写,下面总结一下使用 spEL 去编写 key 可以用的一些元数据: