Spring Cache是Spring3.1以后引入的基于注解的缓存技术,Spring Cache不支持高并发可用性,也不具备持久化数据能力,需要通过第三方缓存来实现持久化,通过@EnableCaching注解可以自动化配置合适的缓存管理器(CacheManager)。
@EnableCaching:
开启Spring Cache功能只需要两步:
1、配置类上开启缓存注解支持:@EnableCaching
2、在容器内声明至少一个CacheManager
类型的Bean
Spring Boot中根据下面的顺序去寻找缓存提供者:
- Generic
- JCache (JSR-107)
- EhCache 2.x
- Hazelcast
- Infinispan
- Redis
- Guava
- Simple
可以通过配置属性spring.cache.type来强制指定
spring.cache.type = redis
也可以创建CacheConfig文件使用如Spring Data提供的RedisCacheManager等直接指定,使用redisCacheManager还可以自己设定缓存过期时间,Spring Cache的default expire time无法修改,需要通过如直接设置redis缓存时间来修改。
Spring Cache的常用注解:
在操作缓存中,一般会有以下几种操作:
1、获取数据:从缓存获得需要数据,如果缓存没有则从数据库查询,再将其保存在缓存;
2、插入数据:先将数据插入数据库中,再保存到缓存中;
3、更新数据:先将数据更新到数据库中,再更新相应缓存数据;
4、 删除数据:先从数据库中删除数据,再删除缓存中数据;
所以在Spring Cache缓存中对应有几种常用注解:@CacheConfig 、@Cacheable、@CachePut、@CacheEvict、@Caching
@CacheConfig:
@CacheConfig的作用是可以在类级别上抽取缓存公共设置,一般用于缓存分组比如所有的@Cacheable()里面都有一个value=“article”的属性,就可以声明一个@CacheConfig(cacheNames = "article") 。
@Cacheable:
@Cacheable适用于获取数据,如果缓存中有数据,不在调用注解方法。
主要的参数
value | 缓存的名称,可以在 spring 配置文件中定义,必须指定至少一个 | 例如: @Cacheable(value=”article”) |
key | 缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合 | 例如: @Cacheable(value=”article”,key=”#id”) |
condition | 缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存 | 例如: @Cacheable(value=”article”,condition=”#article.title.length()>2”) |
unless | 执行后判断,不缓存的条件。unless 接收一个结果为 true 或 false 的表达式,表达式支持 SpEL。当结果为 true 时,不缓存。 | 例如: @Cacheable(value=”article”,key="id",unless="#result == null") |
sync | 用sync=true/false表示是否同步,在多线程的环境中,高并发可能会同时调用接口,达不到缓存的目的,通过sync = true 可以有效的避免缓存击穿的问题。 | 例如: @Cacheable(value=”article”,key="id",sync=true) |
关于condition和unless都能决定是否缓存,但是condition优先级高于unless:
condition 不指定相当于 true,unless 不指定相当于 false
当 condition = false,一定不会缓存;
当 condition = true,且 unless = true,不缓存;
当 condition = true,且 unless = false,不缓存;
@CachePut:
@CachePut适合于插入数据和更新数据。一定会调用真实方法,再将方法返回值保存到缓存;
参数和@Cacheable没什么区别,示例:
@CachePut(key = "'article-'+#article.getId()")
public Object updatArticleCache(Article article) {
mapper.updateById(article);
return article;
}
@CacheEvict:
@CacheEvict适合于删除数据,能够根据一定的条件对缓存进行清空。
参数较于@Cacheable和@CachePut多了两个
allEntries | 是否清空所有缓存内容,缺省为 false,如果指定为 true,则方法调用后将立即清空所有缓存 | @CachEvict(value=”article”,allEntries=true) |
beforeInvocation | 是否在方法执行前就清空,缺省为 false,如果指定为 true,则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法执行抛出异常,则不会清空缓存 | @CachEvict(value=”article”,beforeInvocation=true) |
示例:
@CacheEvict(key = "'article-'+#id")
public Object deleteArticleCache(Long id) {
mapper.deleteById(id);
return id;
}
@Caching:
@Caching用于处理复杂的缓存情况。比如用户新增成功可以根据id缓存一份,再根据电话缓存一份,还要根据电子邮箱缓存一份。
@Caching(put = {
@CachePut(value = "user", key = "#user.id"),
@CachePut(value = "user", key = "#user.telNum"),
@CachePut(value = "user", key = "#user.email")
})
public User save(User user) {
return mapper.insert(user);.
}
最后:
Spring Cache的关键原理就是Spring AOP,通过拦截器实现了方法在调用前、调用后获取方法的入参和返回值,获取注解上的缓存判断条件,key名称,缓存的内容实现对缓存的操作。
Spring Cache注解生成类图解:https://www.processon.com/embed/58afa70be4b0793432a703c9