一、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设置。
二、SpringBoot缓存抽象
Spring从3.1版本开始定义了org.springframework.cache.CacheManager和org.springframework.cache.Cache接口来统一不同的缓存技术,并支持使用JSR-107注解简化开发。
在IDEA中,使用Spring Initializr快速创建Spring Boot项目时,勾选中Cache
后,在配置文件中配置debug=true
,可以查看Spring Boot的自动配置项。
其中关于缓存的配置类如下:
org.springframework.boot.autoconfigure.cache.GenericCacheConfiguration
org.springframework.boot.autoconfigure.cache.JCacheCacheConfiguration
org.springframework.boot.autoconfigure.cache.EhCacheCacheConfiguration
org.springframework.boot.autoconfigure.cache.HazelcastCacheConfiguration
org.springframework.boot.autoconfigure.cache.InfinispanCacheConfiguration
org.springframework.boot.autoconfigure.cache.CouchbaseCacheConfiguration
org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration
org.springframework.boot.autoconfigure.cache.CaffeineCacheConfiguration
org.springframework.boot.autoconfigure.cache.GuavaCacheConfiguration
org.springframework.boot.autoconfigure.cache.SimpleCacheConfiguration
org.springframework.boot.autoconfigure.cache.NoOpCacheConfiguration
启动项目后,可以在控制台看到匹配到的只有SimpleCacheConfiguration
这个自动配置类,而在SimpleCacheConfiguration类中,使用@Bean
注解给容器中注册了一个CacheManager,由此可看Spring Boot默认的CacheManager是ConcurrentMapCacheManager
。
SimpleCacheConfiguration matched:
- Cache org.springframework.boot.autoconfigure.cache.SimpleCacheConfiguration automatic cache type (CacheCondition)
- @ConditionalOnMissingBean (types: org.springframework.cache.CacheManager; SearchStrategy: all) did not find any beans (OnBeanCondition)
几个重要概念和缓存注解:
Cache | 缓存接口,定义缓存的操作。接口的实现有:RedisCache、EhCacheCache、ConcurrentMapCache等 |
---|---|
CacheManager | 缓存管理器,它的作用是管理各种缓存(Cache)组件 |
@Cacheable | 主要是对方法进行配置,它的作用是根据请求参数,将方法的返回值进行缓存 |
@CacheEvict | 它的作用是清空缓存 |
@CachePut | 既调用方法(@CachePut注解的方法必须执行),又更新数据 |
@EnableCaching | 开启基于缓存的注解 |
keyGenerator | 缓存数据时key的生成策略 |
serialize | 缓存数据时value的序列化策略。例如:是使用JDK的序列化方式,还是Json |
@CacheConfig | 抽取缓存的公共配置,例如缓存的名字 @CacheConfig(cacheNames = “xxx”) |
@Caching | 组合注解,定义复杂的缓存规则 |
进入@Caching的源码可以看到,在组合注解内可以使用cacheable、put、evict
public @interface Caching {
Cacheable[] cacheable() default {};
CachePut[] put() default {};
CacheEvict[] evict() default {};
}
@Caching的使用
@Caching(
cacheable = {
@Cacheable(key = "#name")
},
put = {
@CachePut(key = "#result.id"),
@CachePut(key = "#result.cNo")
}
)
@Cacheable、@CachePut、@CacheEvict中的主要参数
value | 缓存的名称,在Spring配置文件中定义,必须指定一个 | 例:@Cacheable(value=“stu”) |
---|---|---|
key | 缓存的key,可以为空,也可以使用SpEL表达式编写 | 例:@Cacheable(value=“stu”,key=“userName”) |
condition | 缓存的条件,可以为空,也可以使用SpEL表达式编写,只有为true才缓存/清除缓存,不管方法执行前后都可以判断 | 例:@Cacheable(value=“stu”,condition=“userName.length()>2”) |
unless | 用于否定缓存,只在方法执行之后判断,也可以使用SpEL表达式编写,true不缓存,false才缓存 | 例:@Cacheable(value=“stu”,unless=“userName == null”) |
- @Cacheable标注的方法执行之前,先查看缓存中有没有这个数据,默认按照参数的值作为key去缓存中查找。如果没有就运行这个方法并将方法的执行结果放入缓存中,之后再调用该方法时,直接使用缓存中的数据即可。
- @CachePut标注的方法必须要执行,它的运行时机是,先调用目标方法,然后将目标方法的结果放入缓存中,但是更新缓存中的数据时,要注意key值,否则缓存中的数据无法更新。
- @CacheEvict这个注解中
allEntries = true
代表要清除某个缓存中的所有数据。beforeInvocation = false
代表缓存的清除在方法执行之后执行,如果出现异常等情况,则不会清除缓存中的数据。这是@CacheEvict注解默认的。beforeInvocation = true
代表缓存的清除在方法执行之前执行,出现异常等情况,也会清除缓存中的数据。 - key的生成策略:key的生成默认使用SimpleKeyGenerator生成的,而SimpleKeyGenerator的生成策略有:
- 如果没有参数:
key=new SimpleKey();
- 如果有一个参数:
key=参数的值
- 如果有多个参数:
key=new SimpleKey(params);
- 如果没有参数: