整天都在讨论使用 SpringBoot,可你居然连缓存都不清楚
缓存技术是一个让所有开发人员又爱又恨的技术,我们爱缓存是因为缓存能给我们带来数量级的响应和流量,但是最迷人的反而最危险,如果缓存用不好也是灾难级别的,特别是一些涉及到公司主要现金流的业务,如果因为我们使用缓存不当,而带给公司一定的损失,不亚于删库跑路的那个大兄弟,那今天我们就来看一下 springboot 的缓存都有那些东西,学习嘛,一点点的来,慢慢积累自己的经验,才能厚积薄发
个人公众号:Java 架构师联盟,每日更新技术好文
一、JSR107 缓存规范
为了缓存开发规范的统一,以及提升系统的扩展性,J2EE 发布了 JSR107 缓存规范。主要是 Java Caching 定义了 5 个接口,分别是 CachingProvider、CacheManager、Cache、Entry、Expiry。
下面我们分开详细的展开看一下
CachingProvider:
可以创建、配置、获取、管理和控制多个 CacheManager,一个 Application 在运行期间可以访问多个 CachingProvider。
CacheManager:
可以创建、配置、获取、管理和控制多个唯一命名的 Cache,这些 Cache 存在于 CacheManager 的上下文中。一个 CacheManager 仅被一个 CachingProvider 所拥有。
Cache:
是一个类似于 Map 的数据结构并临时存储以 Key 为索引的值。一个 Cache 仅被一个 CacheManager 所拥有。
Entry:
是存储在 Cache 中的 Key-Value 对。
Expiry:
每一个缓存在 Cache 中的条目有一个定义的有效期,一旦超过这个时间,该条目就为过期状态,一旦过期,条目将不可访问、更新和删除。其中缓存的有效期可以通过 ExpiryPolicy 设置。
如果说这样讲解让你有点蒙圈的话,那没关系,我们看下面这张图
简单总结一下就是:一个应用里面可以有多个缓存提供者(CachingProvider),一个缓存提供者可以获取到多个缓存管理器(CacheManager),一个缓存管理器管理着不同的缓存(Cache),缓存中是一个个的缓存键值对(Entry),每个 entry 都有一个有效期(Expiry)。缓存管理器和缓存之间的关系有点类似于数据库中连接池和连接的关系。
二、SpringBoot 缓存抽象
在我自己看来,没有源码所有的理论讲解,都是空谈,或者说就是扯淡,所以我们来看一下,缓存的源码级操作
Spring 从 3.1 版本开始定义了 org.springframework.cache.CacheManager 和 org.springframework.cache.Cache 接口来统一不同的缓存技术,并支持使用 JSR-107 注解简化开发。在 IDEA 中,使用 Spring Initializr 快速创建 Spring Boot 项目时,勾选中 Cache 后,在配置文件中配置 debug=true,可以查看 Spring Boot 的自动配置项。其中关于缓存的配置类如下:
启动项目后,可以在控制台看到匹配到的只有 SimpleCacheConfiguration 这个自动配置类,而在 SimpleCacheConfiguration 类中,使用 @Bean 注解给容器中注册了一个 CacheManager,由此可看 Spring Boot 默认的 CacheManager 是 ConcurrentMapCacheManager。
同样的,我们通过一张图形象的展示一下看看
几个重要概念和缓存注解:
进入 @Caching 的源码可以看到,在组合注解内可以使用 cacheable、put、evict
@Caching 的使用
@Cacheable、@CachePut、@CacheEvict 中的主要参数
key
condition
unless
@Cacheable
标注的方法执行之前,先查看缓存中有没有这个数据,默认按照参数的值作为 key 去缓存中查找。如果没有就运行这个方法并将方法的执行结果放入缓存中,之后再调用该方法时,直接使用缓存中的数据即可。
@CachePut
标注的方法必须要执行,它的运行时机是,先调用目标方法,然后将目标方法的结果放入缓存中,但是更新缓存中的数据时,要注意 key 值,否则缓存中的数据无法更新。
@CacheEvict
这个注解中 allEntries = true 代表要清除某个缓存中的所有数据。beforeInvocation = false 代表缓存的清除在方法执行之后执行,如果出现异常等情况,则不会清除缓存中的数据。这是 @CacheEvict
注解默认的。beforeInvocation = true 代表缓存的清除在方法执行之前执行,出现异常等情况,也会清除缓存中的数据。
key 的生成策略
key 的生成默认使用 SimpleKeyGenerator 生成的,而 SimpleKeyGenerator 的生成策略有:如果没有参数:key=new SimpleKey();如果有一个参数:key=参数的值如果有多个参数:key=new SimpleKey(params);
版权声明: 本文为 InfoQ 作者【小Q】的原创文章。
原文链接:【http://xie.infoq.cn/article/713da30f4d18945965409e140】。
本文遵守【CC BY-NC-ND】协议,转载请保留原文出处及本版权声明。
评论