上一章对于 AnnotationCacheOperationSource 中用到的 SpringCacheAnnotationParser 没有细讲完,这篇单独细讲一下。
Spring Cache 的 Operation 解析器
Operation 解析器最底层的接口是 CacheAnnotationParser,我们先来看下这个接口
CacheAnnotationParser
接口的定义十分简单:
1 | public interface CacheAnnotationParser { |
要求了实现类计算出 目标类 或 方法 对应的 CacheOperation 集合。
SpringCacheAnnotationParser
SpringCacheAnnotationParser 实现了 CacheAnnotationParser 这个接口:
1 |
|
从目标类或方法的声明类上取得默认的 CacheConfig,再执行 parseCacheAnnotations 方法进行解析。
我们先看这个 getDefaultCacheConfig 方法:
1 | DefaultCacheConfig getDefaultCacheConfig(Class<?> target) { |
非常简单,就是从类的 @CacheConfig
注解中取出 cacheNames
、keyGenerator
、cacheManager
、cacheResolver
这四个属性值。
parseCacheAnnotations 方法就较为复杂了,需要解析 Cacheable
、CacheEvict
、CachePut
、Caching
四种注解:
1 | private Collection<CacheOperation> parseCacheAnnotations(DefaultCacheConfig cachingConfig, AnnotatedElement ae) { |
这个 lazyInit 就是数组的懒初始化,不解释了:
1 | private <T extends Annotation> Collection<CacheOperation> lazyInit(Collection<CacheOperation> ops) { |
对 Cacheable、CacheEvict、CachePut 进行注解解析
这三者的注解解析大同小异,parseXXXAnnotation(XXX = Cacheable/Evict/Put)的方法实现基本一致:
1 | CacheXXXOperation parseXXXAnnotation(AnnotatedElement ae, DefaultCacheConfig defaultConfig, CacheXXX cacheXXX) { |
除了上文的 8 个字段外,Cacheable 独有 unless 和 sync 字段,Evict 独有 cacheWide(取自注解的 allEntries 字段) 和 beforeInvocation 字段,Put 独有 unless 字段。
对 Caching 进行注解解析
因为 Caching 本身是一个聚合注解,其定义如下:
1 | ({ElementType.METHOD, ElementType.TYPE}) |
所以其需要执行类似 parseCacheAnnotations 的操作,将 Cacheable、CachePut、CacheEvict 三种注解分别转换再聚合起来:
1 | Collection<CacheOperation> parseCachingAnnotation(AnnotatedElement ae, DefaultCacheConfig defaultConfig, Caching caching) { |
SpringCacheAnnotationParser 小结
SpringCacheAnnotationParser 本质上就是将 Cacheable、CacheEvict、CachePut 和 Caching 的注解参数转换成了 CacheOperation 集合的结构。