我正在参与 CSDN《新程序员》有奖征文,活动地址。
你好,我是悟空。
前三篇讲解的缓存使用和分布式锁的都是基于 Redis 来做缓存的,本篇我来向大家介绍一种兼容所有缓存中间件的方案,不论我们是使用 Redis 还是 Ehcache,都不需要关心如何操作 Redis 或者 Ehcache,这套方案统统帮你搞定。
这套方案就是大名鼎鼎的 Spring Cache
。什么?你没有听过,没关系,本篇带你一起探索。
一、揭开 Spring Cache 的面纱
1.1 现有缓存方案的痛点
试想一种场景:
1.用户 A 打开 APP,进入到了秒杀商品的详情页,那这个商品数据我们会先去数据库查询,然后返回给客户端。
2.因为有大量用户短时间内进入到了详情页,所以可以把活动列表缓存起来,直接读缓存就可以了。
3.那下次再查询商品时,直接去缓存查询就可以了。如果秒杀商品下架了,缓存的数据不会用到了,就把缓存删掉就可以了。
4.上面几步看起来也没啥问题,但是放缓存,删除缓存这两步是需要我们去手动写代码实现的。有没有一种方式不用写操作缓存的代码?
5.假如现在用的缓存中间件是 Redis,领导说要换成 Ehcache,操作缓存的代码是不是又得重新撸一遍?
总结下上面场景的痛点:
- 需要手写操作缓存代码,如添加缓存、更新缓存、删除缓存。
- 切换缓存组件并不容易,或者说没有对缓存层进行抽象封装,依赖具体的缓存中间件。
哪有没有一种方案可以帮助解决上面的两个痛点呢?
这就是今天要介绍的 Spring Cache
。
1.2 Spring Cache 介绍
Spring Cache 是 Spring 提供的一整套的缓存解决方案。虽然它本身并没有提供缓存的实现,但是它提供了一整套的接口和代码规范、配置、注解等,这样它就可以整合各种缓存方案了,比如 Redis、Ehcache,我们也就不用关心操作缓存的细节。
Spring 3.1 开始定义了 org.springframework.cache.Cache 和 org.springframework.cache.CacheManager 接口来统一不同的缓存技术,并支持使用注解来简化我们开发。
Cache
接口它包含了缓存的各种操作方式,同时还提供了各种xxxCache
缓存的实现,比如 RedisCache 针对Redis,EhCacheCache 针对 EhCache,ConcurrentMapCache 针对 ConCurrentMap,具体有哪几种,后面实战中会介绍。
1.3 Spring Cache 有什么功效
每次调用某方法,而此方法又是带有缓存功能时,Spring 框架就会检查指定参数
的那个方法是否已经被调用过,如果之前调用过,就从缓存中取之前调用的结果;如果没有调用过,则再调用一次这个方法,并缓存结果,然后再返回结果,那下次调用这个方法时,就可以直接从缓存中获取结果了。
1.4 Spring Cache 的原理是什么?
Spring Cache 主要是作用在类上或者方法上,对类中的方法的返回结果进行缓存。那么如何对方法增强,来实现缓存的功能?
学过 Spring 的同学,肯定能一下子就反应过来,就是用 AOP
(面向切面编程)。
面向切面编程可以简单地理解为在类上或者方法前加一些说明,就是我们常说的注解。
Spring Cache 的注解会帮忙在方法上创建一个切面(aspect),并触发缓存注解的切点(poinitcut),听起来太绕了,简单点说就是:Spring Cache 的注解会帮忙在调用方法之后,去缓存方法调用的最终结果,或者在方法调用之前拿缓存中的结果,或者删除缓存中的结果,这些读、写、删缓存的脏活都交给 Spring Cache 来做了,是不是很爽,再也不用自己去写缓存操作的逻辑了。
1.5 缓存注解
Spring 提供了四个注解来声明缓存规则。@Cacheable,@CachePut,@CacheEvict,@Caching。
大家先有个概念,后面我们再来看怎么使用这些缓存注解。
二、使用缓存
2.1 引入 Spring Cache 依赖
在 pom 文件中引入 spring cache 依赖,如下所示:
<dependency>
<groupId>org.springframework.boot</groupId>
<artif