(Draft)Spring Cache 原理解析

待完善中..

如果你对 spring 事务模块比较熟悉的话,那么理解 Spring Cache 会简单很多,在官方文档中就有提到这个观点,Spring Cache 的实现从框架API 抽象层面来看,和事物基本一样的,都是通过 AOP 来实现,以达到最小化业务侵入。

Similar to the transaction support, the caching abstraction allows consistent use of various caching solutions with minimal impact on the code.

注解解析

在上面 case 中,需要关注几个注解:@CacheConfig,@CachePut,@Cacheable,@CacheEvict,此外也需要关注这些注解的属性;这里我们来看下这些注解是如何被解析,如何生效的。

@CacheConfig

属性 含义 案例
cacheNames/value 缓存的名称 例如: @CachePut(value=”mycache”) @CachePut(cacheNames={”cache1”,”cache2”}
keyGenerator key 生成器
cacheManager 缓存管理器
cacheResolver 用于拦截方法调用的缓存实例

@CachePut

属性 含义 案例
cacheNames/value 缓存的名称 例如: @CachePut(value=”mycache”) @CachePut(value={”cache1”,”cache2”}
key 缓存的 key 例如: @CachePut(value=”testcache”,key=”#userName”)
condition 缓存的条件 例如: @CachePut(value=”testcache”,condition=”#userName.length()>2”)

@Cacheable

属性 含义 案例
cacheNames/value 缓存的名称 每一个缓存名称代表一个缓存对象。当一个方法填写多个缓存名称时将创建多个缓存对象。当多个方法使用同一缓存名称时相同参数的缓存会被覆盖。所以通常情况我们使用“包名+类名+方法名”或者使用接口的RequestMapping作为缓存名称防止命名重复引起的问题。单缓存名称:@Cacheable(value=”mycache”) 多缓存名称:@Cacheable(value={”cache1”,”cache2”}
key 缓存的 key key标记了缓存对象下的每一条缓存。如果不指定key则系统自动按照方法的所有入参生成key,也就是说相同的入参值将会返回同样的缓存结果。如果指定key则要按照 SpEL 表达式编写使用的入参列表。如下列无论方法存在多少个入参,只要userName值一致,则会返回相同的缓存结果。@Cacheable(value=”testcache”,key=”#userName”)
condition 缓存的条件 满足条件后方法结果才会被缓存。不填写则认为无条件全部缓存。条件使用 SpEL表达式编写,返回 true 或者 false,只有为 true 才进行缓存如下例,只有用户名长度大于2时参会进行缓存 @Cacheable(value=”testcache”,condition=”#userName.length()>2”)

@CacheEvict

属性 含义 案例
cacheNames/value 缓存的名称 删除指定名称的缓存对象。必须与下面的其中一个参数配合使用例如: @CacheEvict(value=”mycache”) 或者 @CacheEvict(value={”cache1”,”cache2”}
key 缓存的 key 删除指定key的缓存对象例如: @CacheEvict(value=”testcache”,key=”#userName”)
condition 缓存的条件 删除指定条件的缓存对象例如: @CacheEvict(value=”testcache”,condition=”#userName.length()>2”)
allEntries 方法执行后清空所有缓存 缺省为 false,如果指定为 true,则方法调用后将立即清空所有缓存。例如: @CacheEvict(value=”testcache”,allEntries=true)
beforeInvocation 方法执行前清空所有缓存 缺省为 false,如果指定为 true,则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法执行抛出异常,则不会清空缓存。例如: @CacheEvict(value=”testcache”,beforeInvocation=true)

执行拦截

方法执行

总结

从接口+实现分离的角度思考这种设计带来的好处,对于我们日常工作有哪些启发

参考链接

おすすめ

転載: juejin.im/post/7067090547126566920