Spring Cache 使用教程之一
大纲
前言
官方文档
简单介绍
Spring Cache 是 Spring 提供的一个缓存框架,从 Spring 3.1 版本开始支持将缓存添加到现有的 Spring 应用程序中,从 Spring 在 4.1 版本开始,缓存已支持 JSR-107
注释和更多自定义的选项。Spring Cache 利用了 AOP,实现了基于注解的缓存功能,并且进行了合理的抽象,业务代码不用关心底层是使用了什么缓存框架,只需要简单地加一个注解就能实现缓存功能,做到了较小的代码侵入性。由于市面上的缓存工具实在太多,Spring Cache 框架还提供了 CacheManager 接口,可以实现降低对各种缓存框架的耦合;它不是具体的缓存实现,只是提供一整套的接口和代码规范、配置、注解等,用于整合各种缓存方案,比如 Ehcache、Caffeine、Hazelcast、Couchbase 等。
JSR-107 规范
JSR 是 Java Specification Requests(Java 规范请求)的缩写。JSR-107 是关于如何使用缓存的规范,是 Java 提供的一个接口规范,类似 JDBC 规范,没有具体的实现。Java Caching(JSR-107)定义了 5 个核心接口,分别是 CachingProvider、CacheManager、Cache、Entry 、Expiry。
CachingProvider(缓存提供者)
:用于创建、配置、获取、管理和控制多个 CacheManager。CacheManager(缓存管理器)
:用于创建、配置、获取、管理和控制多个唯一命名的 Cache,一个 CacheManager 仅对应一个 CachingProvider。Cache(缓存)
:存在于 CacheManager 的上下文中,是一个类似 Map 的数据结构,并临时存储以 Key 为索引的值。一个 Cache 仅被一个 CacheManager 所拥有,由 CacheManager 管理其生命周期。Entry(缓存键值对)
:是一个存储在 Cache 中的键值对。Expiry(缓存时效)
:每一个存储在 Cache 中的条目都有一个定义的有效期。一旦超过这个时间,条目就自动过期,过期后条目将不可以执行访问、更新和删除操作。缓存有效期可以通过 ExpiryPolicy 设置。
Spring Cache 概念
大致原理
在 Spring Cache 官网中,有一个缓存抽象的概念,其核心就是将缓存应用于 Java 方法中,从而减少基于缓存中可用信息的执行次数。换句话来说,就是每次调用目标方法前,Spring Cache 都会先检查该方法是否正对给定参数执行,如果已经执行过,就直接返回缓存的结果。通俗的讲,就是查看缓存里面是否有对应的数据,如果有就返回缓存数据,而无需执行实际方法;如果该方法尚未执行,则执行该方法(缓存中没有对应的数据就执行方法来获取对应的数据),并缓存结果后返回给用户。这样就不用多次去执行数据库操作,减少 CPU 和 IO 的消耗。
使用 Spring 缓存抽象时,应该需要关注以下两点
- 1、确定方法需要被缓存以及它们的缓存策略
- 2、从缓存中读取之前缓存存储的数据
核心接口
org.springframework.cache.Cache
:为缓存组件定义规范,包含缓存的各种操作集合。在 Cache 接口下,Spring 提供了各种xxxCache
的实现,如 RedisCache、EhCacheCache、ConcurrentMapCache 等。org.springframework.cache.CacheManager
:缓存管理器,管理各种缓存(Cache)组件,如 RedisCacheManager,使用 Redis 作为缓存。
核心注解
注解 | 说明 |
---|---|
@Cacheable | 主要针对方法配置,能够根据方法的请求参数对其执行结果进行缓存,相当于缓存使用的是读模式 |
@CacheEvict | 将一条或多条数据从缓存中删除,相当于缓存使用的是写模式中的失效模式 |
@CachePut | 保证方法被调用,又希望结果被缓存,相当于缓存使用的是写模式中的双写模式 |
@EnableCaching | 开启基于注解的缓存功能 |
@CacheConfig | 标注在类上,用于抽取 Spring Cache 相关注解的公共配置,可抽取的公共配置包括缓存名称、主键生成器、缓存管理器 |
@Caching | 用于在一个方法或者类上,同时指定多个 Spring Cache 相关的注解 |
keyGenerator | 缓存数据时 Key 的生成策略 |
serialize | 缓存数据时 Value 的序列化策略 |
在上面常用的三个注解 @Cacheable
、@CachePut
、CacheEvict
中,主要有以下的参数,可用于对要缓存的数据进行过滤和配置。
提示
- 1、
@Cacheable
标注在方法上,表示方法的结果需要被缓存起来,缓存的键由keyGenerator
的策略决定,缓存的值的形式则由serialize
序列化策略决定(JDK 还是 Json 序列化机制);标注上该注解之后,在缓存时效内再次调用该方法时不会调用方法本身,而是直接从缓存获取结果。 - 2、
@CachePut
也标注在方法上,它和@Cacheable
相似也会将方法的返回值缓存起来,不同的是标注@CachePut
的方法每次都会被调用,而且每次都会将结果缓存起来,适用于对象的更新。
Spring Cache 整合
下面将介绍 Spring Boot 项目如何整合 Spring Cache,并使用 Redis 存储缓存数据。
引入依赖
1 | <dependency> |
配置信息
在 application.yml
配置文件里,指定 Spring Cache 使用 Redis 存储缓存数据,并配置 Redis 的连接信息。
1 | spring: |
启用缓存
在应用的主启动类上添加 @EnableCaching
注解,启用 Spring Cache 的缓存功能。
1 |
|
配置序列化
默认情况下,Spring Cache 会使用 JDK 的序列化机制将缓存数据写入 Redis,这样存储在 Redis 里面的就是二进制数据。若希望 Spring Cache 将数据序列化成 JSON 数据再写入 Redis,可以使用以下的配置类。
1 | import org.springframework.boot.autoconfigure.cache.CacheProperties; |
添加缓存注解
在需要使用缓存的方法上添加 @Cacheable
注解,其中的 value
参数代表缓存的名称,必须指定至少一个。标注上该注解之后,会将方法运行的结果进行缓存,在缓存时效内再次调用该方法时不会调用方法本身,而是直接从缓存获取结果并返回给调用方。
1 |
|
至此,Spring Boot 项目整合 Spring Cache 的步骤就完成了。当重复调用标记了 @Cacheable
注解的方法时,可以发现该方法只会被调用一次,此时说明 Redis 的缓存生效了。