一、spring缓存注解
0、配置
开启基于注解的缓存,使用 @EnableCaching
标识在 SpringBoot 的主启动类上。
配置文件添加:spring.cache.type=simple
1、查缓存@Cacheable
(1)属性介绍
根据方法对其返回结果进行缓存,下次请求时,如果缓存存在,则直接读取缓存数据返回;如果缓存不存在,则执行方法,并把返回的结果存入缓存中。一般用在查询方法上。
查看源码,属性值如下:
属性/方法名 | 解释 |
---|---|
value | 缓存名,必填,它指定了你的缓存存放在哪块命名空间 |
cacheNames | 与 value 差不多,二选一即可 |
key | 可选属性,可以使用 SpEL 标签自定义缓存的key |
其他属性
cacheNames/value
:用来指定缓存组件的名字,可以是数组的方式,支持指定多个缓存。key
:缓存数据时使用的 key,可以用它来指定。默认是使用方法参数的值。(这个 key 你可以使用 spEL 表达式来编写)keyGenerator
:key 的生成器。 key 和 keyGenerator 二选一使用cacheManager
:可以用来指定缓存管理器。从哪个缓存管理器里面获取缓存。condition
:可以用来指定符合条件的情况下才缓存unless
:否定缓存。当 unless 指定的条件为 true ,方法的返回值就不会被缓存。当然你也可以获取到结果进行判断。(通过#result
获取方法结果)sync
:是否使用异步模式。默认是方法执行完,以同步的方式将方法返回的结果存在缓存中。
(2)基本使用
下面代码是将 service 业务层的结果作为缓存,首次调用的时候会执行方法内容,再次调用时不执行
当参数为1时,缓存的 key 为 MENU:1
,value 为 id:1
@Cacheable(value = "MENU:",key = "#id")
@Override
public String getMenu(String id) {
System.out.println(id);
return "id:" + id;
}
当参数是对象时
@Cacheable(value="users", key="#user.id")
public User find(User user) {
return null;
}
(3)方法执行条件
有的时候我们可能并不希望缓存一个方法所有的返回结果。通过condition属性可以实现这一功能。
condition属性默认为空,表示将缓存所有的调用情形。其值是通过SpringEL表达式来指定的,当为true时表示进行缓存处理;当为false时表示不进行缓存处理,即每次调用该方法时该方法都会执行一次。如下示例表示只有当user的id为偶数时才会进行缓存。
@Cacheable(value={"users"}, key="#user.id", condition="#user.id%2==0")
public User find(User user) {
System.out.println("find user by user " + user);
return user;
}
2、加缓存@CachePut
使用该注解标志的方法,每次都会执行,并将结果存入指定的缓存中。其他方法可以直接从响应的缓存中读取缓存数据,而不需要再去查询数据库。一般用在新增方法上。
与@Cacheable不同的是使用@CachePut标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中。
查看源码,属性值如下:
属性/方法名 | 解释 |
---|---|
value | 缓存名,必填,它指定了你的缓存存放在哪块命名空间 |
cacheNames | 与 value 差不多,二选一即可 |
key | 可选属性,可以使用 SpEL 标签自定义缓存的key |
3、清缓存@CacheEvict
使用该注解标志的方法,会清空指定的缓存。一般用在更新或者删除方法上
查看源码,属性值如下:
属性/方法名 | 解释 |
---|---|
value | 缓存名,必填,它指定了你的缓存存放在哪块命名空间 |
cacheNames | 与 value 差不多,二选一即可 |
key | 可选属性,可以使用 SpEL 标签自定义缓存的key |
allEntries | 是否清空所有缓存,默认为 false。如果指定为 true,则方法调用后将立即清空所有的缓存 |
beforeInvocation | 是否在方法执行前就清空,默认为 false。如果指定为 true,则在方法执行前就会清空缓存 |
清除操作默认是在对应方法成功执行之后触发的,即方法如果因为抛出异常而未能成功返回时也不会触发清除操作。使用beforeInvocation可以改变触发清除操作的时间,当我们指定该属性值为true时,Spring会在调用该方法之前清除缓存中的指定元素。
@CacheEvict(value="users", beforeInvocation=true)
public void delete(Integer id) {
System.out.println("delete user by id: " + id);
}
4、@Caching
@Caching
注解可以让我们在一个方法或者类上同时指定多个Spring Cache相关的注解。其拥有三个属性:cacheable、put和evict,分别用于指定@Cacheable、@CachePut和@CacheEvict。
@Caching(
cacheable = @Cacheable("users"),
evict = {
@CacheEvict("cache2"),
@CacheEvict(value = "cache3", allEntries = true)
}
)
public User find(Integer id) {
retur null;
}
5、自定义注解
Spring允许我们在配置可缓存的方法时使用自定义的注解,前提是自定义的注解上必须使用对应的注解进行标注。如我们有如下这么一个使用 @Cacheable
进行标注的自定义注解。
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Cacheable(value="users")
public @interface MyCacheable {undefined
}
那么在我们需要缓存的方法上使用 @MyCacheable
进行标注也可以达到同样的效果。
@MyCacheable
public User findById(Integer id) {
System.out.println("find user by id: " + id);
User user = new User();
user.setId(id);
user.setName("Name" + id);
return user;
}
补充、SpEL 标签
属性名称 | 描述 | 示例 |
---|---|---|
methodName | 当前方法名 | #root.methodName |
method | 当前方法 | #root.method.name |
target | 当前被调用的对象 | #root.target |
targetClass | 当前被调用的对象的class | #root.targetClass |
args | 当前方法参数组成的数组 | #root.args[0] |
caches | 当前被调用的方法使用的Cache | #root.caches[0].name |
argument name | 方法参数名,可以直接使用 #参数名,也可以用#p0或#a0,0代表参数的索引 | #id、#user.id |
result | 方法执行后的返回值(仅当方法执行后的判断有效) | #result |
二、CacheManager
1、Cache接口
Cache接口:主要是缓存的增删查功能。
package org.springframework.cache;
public interface Cache {
String getName(); //缓存的名字
Object getNativeCache(); //得到底层使用的缓存,如Ehcache
ValueWrapper get(Object key); //根据key得到一个ValueWrapper,
然后调用其get方法获取值
<T> T get(Object key, Class<T> type);//根据key,和value的类型直接获取value
void put(Object key, Object value);//往缓存放数据
void evict(Object key);//从缓存中移除key对应的缓存
void clear(); //清空缓存
interface ValueWrapper { //缓存值的Wrapper
Object get(); //得到真实的value
}
}
由此可见,缓存的对象就是键值对。
默认实现:
- ConCurrentMapCache:使用java.util.concurrentHashMap实现的Cache。
- GuavaCache: 对Gguava com.google.common.cache.Cache进行的Wrapper,需要Google Guava 12.0或更高版本。
- EhCacheCache: 使用Ehcache实现。
- JCacheCache:对javax.cache.Cache进行的Wrapper。
2、CacheManager接口
CacheManager:Spring提供的缓存管理器,便于管理程序中的多个cache。
public interface CacheManager {
Cache getCache(String name); //根据Cache名字获取Cache
Collection<String> getCacheNames(); //得到所有Cache的名字
}
默认实现:
- SimpleCacheManager
- NoOpCacheManager
- ConcurrentMapCacheManager
- CompositeCacheManager
- EhCacheCacheManager
- RedisCacheManager: 来自spring data redis项目
- GemfireCacheManager:来自spring data gemfire项目
具体要选择哪个取决于要使用的底层缓存。
另外还提供了CompositeCacheManager用于组合CacheManager,即可以从多个CacheManager轮询得到相应的cache。