在上文介绍了 jsr-107 规范 后, 本文来介绍一下 spring 缓存机制相关内容。
1.spring 缓存机制介绍
spring 从 3.1开始,针对缓存定义了org.springframework.cache.cache
和org.springframework.cache.cachemanager
接口,来统一不同的缓存技术。
并支持使用 jcache(jsr-107规范)注解来简化项目的开发。
spring 的缓存机制非常灵活,可以对容器中任意 bean 或者 bean 的方法进行缓存,因此这种缓存机制可以在 javaee 应用的任何层次上进行缓存。在缓存的具体实现上,spring 缓存底层也是借助其他缓存工具来实现的,例如 ehcache(hibernate缓存工具),上层则以统一 api 编程。
spring 缓存机制,cache接口
为缓存的组件规范定义,包扩缓存的各种操作 (添加缓存、删除缓存、修改缓存等) 。在 cache 接口下,spring 为其提供了各种 xxxcache 的实现。如:rediscache
、ehcachecache
、concurrentmapcache
等;
2.spring 缓存用到的概念
ⅰ.两个接口
cache
:缓存接口,用来定义缓存的各种操作。spring提供的具体实现有:rediscache、ehcachecache、concurrentmapcache等;cachemanager
:缓存管理器,管理各种缓存(cache)组件
ⅱ.三个注解(方法层次)
@cacheable
:标注在方法上,能够根据方法的请求参数等对其结果进行缓存。代表一个方法能被缓存@cacheevict
:清空缓存(标注在删除方法上,用来清空缓存)@cacheput
:更新缓存。保证方法被调用,同时更新后的结果被缓存。
ⅲ.一个注解(功能层次)
@enablecaching
:开启基于注解的缓存(想要使用缓存,就需要开启缓存注解) ⅳ.两个自定义keygenerator
:缓存数据时key生成策略serialize
:缓存数据时 value 值序列化策略
3.工作原理
每次调用需要缓存功能的方法时,spring 都会检查指定参数的指定的目标方法是否已经被调用过;如果有就直接从缓存中获取方法调用后的结果,如果没有就调用方法并缓存结果后返回给用户。下次调用直接从缓存中获取。
4.缓存在项目中的使用
我们来准备一个环境,使用 spring boot + mybatis 框架,来展示一下缓存在项目中的使用。此处就不啰嗦环境的搭建过程了,直接来介绍 cache 缓存在项目中的使用。如需项目demo,请跳转至文末代码部分。
ⅰ.使用@enablecaching 开启基于注解的缓存
@springbootapplication @mapperscan("com.example.cache.mapper") @enablecaching //开启基于注解的缓存 public class cacheapplication { public static void main(string[] args) { springapplication.run(cacheapplication.class, args); } }
ⅱ.来个controller
提示:此处的3个方法分别对应 @cacheable、@cacheput、@cacheevict 三个注解,接下来一一测试
@restcontroller public class usercontroller { @autowired userservice userservice; /** * 根据id获取用户信息(主要针对 @cacheable 注解介绍) */ @getmapping("/user/{id}") public user user(@pathvariable("id") integer id){ user user = userservice.getuser(id); return user; } /** * 更新用户信息(主要针对 @cacheput 注解介绍) */ @putmapping("/user") public user updateuser(user user) { user upuser = userservice.updateuser(user); return upuser; } /** * 根据id删除用户数据(主要针对 @cacheevict 注解介绍) */ @deletemapping("/user/{id}") public void deleteuser(@pathvariable("id") integer id) { userservice.deleteuser(id); } }
ⅲ.在需要缓存的方法上,添加@cacheable注解,表示该方法需要被缓存
public interface userservice { /** * 根据id获取用户信息 * 此处 value 为 @cacheable 属性,该注解还有很多属性,在 https://blog.csdn.net/lzb348110175/article/details/105349109 会有介绍,此处不做介绍 * 缓存相关注解,也可以写到具体service实现类上,此处写在了接口上 */ @cacheable(value = "user"/*,key="#id"*/) user getuser(integer id); /** * 更新用户信息 */ @cacheput(value = "user",key = "#user.id") user updateuser(user user); /** * 根据id删除用户 */ @cacheevict(value = "user", key = "#id") void deleteuser(integer id); }
ⅳ.getuser()方法实现
@service @slf4j public class userserviceimpl implements userservice { @autowired usermapper usermapper; /** * 根据id获取用户信息 */ @override public user getuser(integer id) { log.info("用户"+id+"开始执行数据库查询"); return usermapper.getuser(id); } /** * 更新用户信息 */ @override public user updateuser(user user) { log.info("开始更新用户"+user.getid()+"的数据信息"); usermapper.updateuser(user); return user; } /** * 删除用户(此处仅演示删除缓存数据,实际数据库数据不删除,方便演示) */ @override public void deleteuser(integer id) { system.out.println("执行删除缓存数据操作"); } }
ⅴ.测试@cacheable缓存配置是否生效
- 第一步:分别调用
http://localhost:8080/user/1
和http://localhost:8080/user/2
请求,第一次请求时会调用数据库查询。 - 第二步:当再次发送相同请求时,由于缓存中数据已经存在,所以会通过缓存来获取数据而不去读取数据库。
@cacheable注解共有9个属性可配置,这些属性的配置可参考:@cacheable注解属性介绍。
@cacheable注解相关属性介绍
@cacheable 注解提供的属性,如何配置可参考:@cacheable注解属性介绍。
ⅵ.测试@cacheput 是否会更新缓存
- 第一步:我们来调用
http://localhost:8080/user/1
接口,该接口首先会将返回的数据存入缓存。 - 第二步:我们来调用
http://localhost:8080/user
接口来更新id=1
的用户。 - 第三步:再发送第一步中相同请求时,便会通过缓存来获取数据而不去读取数据库,此时返回的内容是已经更新后的数据。
测试结果如下:第一次请求,查询数据库返回 mary
;第二次请求,更新数据为clark
;第三次再次发送查询请求,在更新数据时缓存会同时被更改,由于缓存存在,所以不会调用数据库请求,返回的是修改后的缓存中的数据clark
。(切记:更新缓存时的 key 要与已经存在缓存中的数据 key 相同,否则缓存不会被更新。)
@cacheput 注解相关属性介绍
@cacheput 注解提供的属性,如何配置可参考:@cacheable注解属性介绍。(此处附的参考文章是正确的,我没有附错,因为它们配置都是一样紫的)
ⅶ.测试@cacheevict 是否会删除缓存
- 第一步:我们来调用
http://localhost:8080/user/1
接口,该接口首先会将返回的数据存入缓存。 - 第二步:继续调用该接口,便会从缓存来获取数据。
- 第三步:调用
http://localhost:8080/user/1
(发送的是 delete 请求)执行缓存删除操作。 - 第四步:继续发送第一步请求操作,由于缓存已经被删除,所以当前请求操作会再次去数据库查询。
@cacheevict 注解相关属性介绍
@cacheevict 注解提供的属性,如何配置可参考:@cacheable注解属性介绍。(此处附的参考文章是正确的,我没有附错,因为它们配置都是一样紫的)(切记:删除缓存时的 key 要与已经存在缓存中的数据 key 相同,否则缓存不会被删除。)除此之外,@cacheevict 注解还提供了额外两个属性:allentries
、beforeinvocation
。这两个属性如何使用,介绍如下:
allentries
:清除指定缓存中的所有数据,默认为 false;(使用该属性就不需要使用 key 属性了)-
allentries = false,默认代表清除这个缓存中指定 key 的数据。
-
allentries = true,指定清除这个缓存中所有的数据。
beforeinvocation
:清除缓存的操作是否在方法之前执行,默认为false;-
beforeinvocation = false,默认代表缓存清除操作是在方法执行之后执行;如果出现异常缓存就不会清除。
beforeinvocation = true,代表清除缓存操作是在方法运行之前执行,无论方法是否出现异常,缓存都清除。
ⅷ.(了解)@caching注解—应用于复杂缓存规则的指定
//可以使用@caching 来解决满足项目开发的复杂缓存规则 @caching( cacheable = { @cacheable(value = "user",key = "#name") }, put = { @cacheput(value = "user",key = "#result.id"), @cacheput(value = "user",key = "#result.email") }, evict = { @cacheevict(value = "user",key = "#name") } ) user getuserbyname(string name);
ⅸ.(了解)@cacheconfig注解—应用于抽取当前类下缓存使用的公共配置
比如 userservice 类下的所有操作,①缓存都是存在 key = “user” 下,②使用的 keygenerator 都是我们自定义的,那么我们可以使用 @cacheconfig 注解来抽取缓存的公共配置,并将该注解标注在该 userservice类上即可。
(公共配置支持:cachenames
、keygenerator
、cachemanager
、cacheresolver
4个属性的配置)
@cacheconfig(cachenames="emp",cachemanager = "employeecachemanager",keygenerator = "mykeygenerator",cacheresolver = "mycacheresolver") //抽取缓存的公共配置 public interface userservice{ //代码省略 }
5.附上demo
spring cache 缓存使用demo
百度网盘下载地址:
链接: https://pan.baidu.com/s/1nxuotauqihsiqrd7bifi5w
提取码: 2jyz
到此这篇关于spring 缓存在项目中的使用的文章就介绍到这了,更多相关spring 缓存在项目使用内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论