SpringCache源码| SpringCache缓存注解解析

1.缓存的解析

Spring Cache提供了缓存解析器,负责为缓存注解抽象成一个缓存信息对象。我们通过面向对象的编程方式就能够轻松的获取缓存操作信息

1.1CacheAnnotationParser缓存注解解析器

1
2
3
4
5
6
7
8
public interface CacheAnnotationParser {
//对类上面的缓存注解进行解析
@Nullable
Collection<CacheOperation> parseCacheAnnotations(Class<?> var1);
//对方法上面的注解进行解析
@Nullable
Collection<CacheOperation> parseCacheAnnotations(Method var1);
}

CacheAnnotationParser有一个实现类SpringCacheAnnotationParser,两个方法的实现是一样的,最终method也会转换成Class。所以这里针对parseCacheAnnotations(Class<?> var1)做解析

1
2
3
4
5
6
7
8
9
10
11
12
@Nullable
public Collection<CacheOperation> parseCacheAnnotations(Class<?> type) {
//1. 获取
SpringCacheAnnotationParser.DefaultCacheConfig defaultConfig = this.getDefaultCacheConfig(type);
//2. 通过DefaultCacheConfig信息和class去解析缓存注解
return this.parseCacheAnnotations(defaultConfig, type);
}
@Nullable
public Collection<CacheOperation> parseCacheAnnotations(Method method) {
SpringCacheAnnotationParser.DefaultCacheConfig defaultConfig = this.getDefaultCacheConfig(method.getDeclaringClass());
return this.parseCacheAnnotations(defaultConfig, method);
}

1.2getDefaultCacheConfig

1
2
3
4
5
6
SpringCacheAnnotationParser.DefaultCacheConfig getDefaultCacheConfig(Class<?> target) {
//获取类上面的@CacheConfig注解信息
CacheConfig annotation = (CacheConfig)AnnotatedElementUtils.findMergedAnnotation(target, CacheConfig.class);
//如果@CacheConfig不存在,则构建一个默认的DefaultCacheConfig
return annotation != null ? new SpringCacheAnnotationParser.DefaultCacheConfig(annotation.cacheNames(), annotation.keyGenerator(), annotation.cacheManager(), annotation.cacheResolver()) : new SpringCacheAnnotationParser.DefaultCacheConfig();
}

1.3. parseCacheAnnotations

1
2
3
4
5
6
7
8
9
10
11
12
@Nullable
private Collection<CacheOperation> parseCacheAnnotations(SpringCacheAnnotationParser.DefaultCacheConfig cachingConfig, AnnotatedElement ae) {
Collection<CacheOperation> ops = this.parseCacheAnnotations(cachingConfig, ae, false);
if (ops != null && ops.size() > 1 && ae.getAnnotations().length > 0) {
Collection<CacheOperation> localOps = this.parseCacheAnnotations(cachingConfig, ae, true);
if (localOps != null) {
return localOps;
}
}

return ops;
}

这个方法只是一个空壳,真正的逻辑在this.parseCacheAnnotations(cachingConfig, ae, false)这里面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
@Nullable
private Collection<CacheOperation> parseCacheAnnotations(SpringCacheAnnotationParser.DefaultCacheConfig cachingConfig, AnnotatedElement ae, boolean localOnly) {
Collection<CacheOperation> ops = null;
//解析@Cacheable
Collection<Cacheable> cacheables = localOnly ? AnnotatedElementUtils.getAllMergedAnnotations(ae, Cacheable.class) : AnnotatedElementUtils.findAllMergedAnnotations(ae, Cacheable.class);
if (!cacheables.isEmpty()) {
ops = this.lazyInit((Collection)null);
Iterator var6 = cacheables.iterator();

while(var6.hasNext()) {
Cacheable cacheable = (Cacheable)var6.next();
ops.add(this.parseCacheableAnnotation(ae, cachingConfig, cacheable));
}
}
//解析@cacheEvict
Collection<CacheEvict> evicts = localOnly ? AnnotatedElementUtils.getAllMergedAnnotations(ae, CacheEvict.class) : AnnotatedElementUtils.findAllMergedAnnotations(ae, CacheEvict.class);
if (!evicts.isEmpty()) {
ops = this.lazyInit(ops);
Iterator var13 = evicts.iterator();

while(var13.hasNext()) {
CacheEvict evict = (CacheEvict)var13.next();
ops.add(this.parseEvictAnnotation(ae, cachingConfig, evict));
}
}
//解析@CachePut
Collection<CachePut> puts = localOnly ? AnnotatedElementUtils.getAllMergedAnnotations(ae, CachePut.class) : AnnotatedElementUtils.findAllMergedAnnotations(ae, CachePut.class);
if (!puts.isEmpty()) {
ops = this.lazyInit(ops);
Iterator var15 = puts.iterator();

while(var15.hasNext()) {
CachePut put = (CachePut)var15.next();
ops.add(this.parsePutAnnotation(ae, cachingConfig, put));
}
}
//解析Cache
Collection<Caching> cachings = localOnly ? AnnotatedElementUtils.getAllMergedAnnotations(ae, Caching.class) : AnnotatedElementUtils.findAllMergedAnnotations(ae, Caching.class);
if (!cachings.isEmpty()) {
ops = this.lazyInit(ops);
Iterator var17 = cachings.iterator();

while(var17.hasNext()) {
Caching caching = (Caching)var17.next();
Collection<CacheOperation> cachingOps = this.parseCachingAnnotation(ae, cachingConfig, caching);
if (cachingOps != null) {
ops.addAll(cachingOps);
}
}
}

return ops;
}

由上可知,代码分别对@Cacheable,@CachePut,@CacheEvict进行解析,一旦发现相应的注解,就对注解信息封装成对应的CacheOperation(缓存操作信息对象)。封装过程的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
CacheableOperation parseCacheableAnnotation(AnnotatedElement ae, SpringCacheAnnotationParser.DefaultCacheConfig defaultConfig, Cacheable cacheable) {
Builder builder = new Builder();
builder.setName(ae.toString());
builder.setCacheNames(cacheable.cacheNames());
builder.setCondition(cacheable.condition());
builder.setUnless(cacheable.unless());
builder.setKey(cacheable.key());
builder.setKeyGenerator(cacheable.keyGenerator());
builder.setCacheManager(cacheable.cacheManager());
builder.setCacheResolver(cacheable.cacheResolver());
builder.setSync(cacheable.sync());
defaultConfig.applyDefault(builder);
CacheableOperation op = builder.build();
//验证key()与keyGenerator() 以及CacheManager与CacheResolver之间的排他性。代码逻辑如下。
this.validateCacheOperation(ae, op);
return op;
}
1
2
3
4
5
6
7
private void validateCacheOperation(AnnotatedElement ae, CacheOperation operation) {
if (StringUtils.hasText(operation.getKey()) && StringUtils.hasText(operation.getKeyGenerator())) {
throw new IllegalStateException("Invalid cache annotation configuration on '" + ae.toString() + "'. Both 'key' and 'keyGenerator' attributes have been set. These attributes are mutually exclusive: either set the SpEL expression used tocompute the key at runtime or set the name of the KeyGenerator bean to use.");
} else if (StringUtils.hasText(operation.getCacheManager()) && StringUtils.hasText(operation.getCacheResolver())) {
throw new IllegalStateException("Invalid cache annotation configuration on '" + ae.toString() + "'. Both 'cacheManager' and 'cacheResolver' attributes have been set. These attributes are mutually exclusive: the cache manager is used to configure adefault cache resolver if none is set. If a cache resolver is set, the cache managerwon't be used.");
}
}

1.4小结

由此Spring Cache通过缓存注解解析器,将对应的缓存注解解析成了CacheOperation对象,CacheOperation对象封装了缓存注解信息的细节,可以指导相应的缓存操作。

2.谈谈CacheOperation缓存封装类

1
2
3
4
5
6
7
8
9
10
public abstract class CacheOperation implements BasicOperation {
private final String name;
private final Set<String> cacheNames;
private final String key;
private final String keyGenerator;
private final String cacheManager;
private final String cacheResolver;
private final String condition;
private final String toString;
}

CacheOperation是一个抽象的缓存操作类,它封装了Cache操作的基本属性,是对缓存信息的抽象

  1. CacheableOperation(@Cacheable)
  2. CachePutOperation(@CachePut)
  3. CacheEvictOperation(@CacheEvict)

3.缓存操作资源类

Spring Cache提供了一个缓存操作资源接口(CacheOperationSource)来调用缓存注解的解析工作。

1
2
3
4
5
public interface CacheOperationSource {
//为一个执行方法返回所有的缓存操作集合
@Nullable
Collection<CacheOperation> getCacheOperations(Method var1, @Nullable Class<?> var2);
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
@Configuration
@Role(2)
public class ProxyCachingConfiguration extends AbstractCachingConfiguration {
public ProxyCachingConfiguration() {
}

@Bean(
name = {"org.springframework.cache.config.internalCacheAdvisor"}
)
@Role(2)
public BeanFactoryCacheOperationSourceAdvisor cacheAdvisor() {
BeanFactoryCacheOperationSourceAdvisor advisor = new BeanFactoryCacheOperationSourceAdvisor();
advisor.setCacheOperationSource(this.cacheOperationSource());
advisor.setAdvice(this.cacheInterceptor());
if(this.enableCaching != null) {
advisor.setOrder(((Integer)this.enableCaching.getNumber("order")).intValue());
}

return advisor;
}

@Bean
@Role(2)
public CacheOperationSource cacheOperationSource() {
return new AnnotationCacheOperationSource();
}

@Bean
@Role(2)
public CacheInterceptor cacheInterceptor() {
CacheInterceptor interceptor = new CacheInterceptor();
interceptor.configure(this.errorHandler, this.keyGenerator, this.cacheResolver, this.cacheManager);
interceptor.setCacheOperationSource(this.cacheOperationSource());
return interceptor;
}
}

在@Enable文章的代码解析中,在创建Advisor的时候将CacheOperationSource作为属性传递进去了。那么在方法调用时,AOP会通过CacheInterceptor拦截方法,调用CacheOperationSource获取解析方法上面的缓存注解。

CacheOperationSource有三个实现类,Spring Cache采用AnnotationCacheOperationSource来处理缓存注解的解析工作。

查看AnnotationCacheOperationSource的继承体系。

CacheOperationSource的设计采用的是模板模式的方式,获取CacheOperation的主要的通用逻辑在父类AbstractFallbackCacheOperationSource中,子类AnnotationCacheOperationSource主要实现差异化的功能,接下来看一下他们的实现代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public class AnnotationCacheOperationSource extends AbstractFallbackCacheOperationSource implements Serializable {
//省略了部分代码

//只允许public方法 执行缓存操作
private final boolean publicMethodsOnly;
//缓存注解解析器
private final Set<CacheAnnotationParser> annotationParsers;

//获取Class上面对应的缓存操作(实现父类的方法,方法的调用的父类中)
@Nullable
protected Collection<CacheOperation> findCacheOperations(Class<?> clazz) {
return this.determineCacheOperations((parser) -> {
return parser.parseCacheAnnotations(clazz);
});
}

//获取Method上面对应的缓存操作(实现父类的方法,方法的调用的父类中)
@Nullable
protected Collection<CacheOperation> findCacheOperations(Method method) {
return this.determineCacheOperations((parser) -> {
return parser.parseCacheAnnotations(method);
});
}

//遍历解析器集合,获取所有的CacheOperation
@Nullable
protected Collection<CacheOperation> determineCacheOperations(AnnotationCacheOperationSource.CacheOperationProvider provider) {
Collection<CacheOperation> ops = null;
Iterator var3 = this.annotationParsers.iterator();

while(var3.hasNext()) {
CacheAnnotationParser annotationParser = (CacheAnnotationParser)var3.next();
Collection<CacheOperation> annOps = provider.getCacheOperations(annotationParser);
if (annOps != null) {
if (ops == null) {
ops = annOps;
} else {
Collection<CacheOperation> combined = new ArrayList(((Collection)ops).size() + annOps.size());
combined.addAll((Collection)ops);
combined.addAll(annOps);
ops = combined;
}
}
}

return (Collection)ops;
}
//调用CacheAnnotationParser进行注解解析的函数式接口
@FunctionalInterface
protected interface CacheOperationProvider {
@Nullable
Collection<CacheOperation> getCacheOperations(CacheAnnotationParser var1);
}
}

3.1查看AbstractFallbackCacheOperationSource源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
public abstract class AbstractFallbackCacheOperationSource implements CacheOperationSource {
private static final Collection<CacheOperation> NULL_CACHING_ATTRIBUTE = Collections.emptyList();

//维护了一个缓存操作类的map, key为method和class的包装,可以确保唯一性。
private final Map<Object, Collection<CacheOperation>> attributeCache = new ConcurrentHashMap(1024);

//执行缓存注解解析工作的主要逻辑
@Nullable
public Collection<CacheOperation> getCacheOperations(Method method, @Nullable Class<?> targetClass) {
if (method.getDeclaringClass() == Object.class) {
return null;
} else {
//获取method和class组成的唯一key
Object cacheKey = this.getCacheKey(method, targetClass);
//从缓存中去查找CacheOperation.
Collection<CacheOperation> cached = (Collection)this.attributeCache.get(cacheKey);
if (cached != null) {
return cached != NULL_CACHING_ATTRIBUTE ? cached : null;
} else {
//如果attributeCache没有发现,则进行缓存操作的解析
Collection<CacheOperation> cacheOps = this.computeCacheOperations(method, targetClass);
if (cacheOps != null) {
if (this.logger.isTraceEnabled()) {
this.logger.trace("Adding cacheable method '" + method.getName() + "' with attribute: " + cacheOps);
}
将解析结构存入attributeCache,供下次使用
this.attributeCache.put(cacheKey, cacheOps);
} else {
this.attributeCache.put(cacheKey, NULL_CACHING_ATTRIBUTE);
}

return cacheOps;
}
}
}

//获取由Method和Class产生的唯一key
protected Object getCacheKey(Method method, @Nullable Class<?> targetClass) {
return new MethodClassKey(method, targetClass);
}
//开始解析缓存注解
@Nullable
private Collection<CacheOperation> computeCacheOperations(Method method, @Nullable Class<?> targetClass) {
//判断非pulic方法 是否可以获取缓存注解信息
if (this.allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;
} else {
//找到特定的方法
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);

//调用子类实现 从方法上找缓存注解
Collection<CacheOperation> opDef = this.findCacheOperations(specificMethod);
if (opDef != null) {
return opDef;
} else {
//调用子类实现,试着从Class上获取缓存注解
opDef = this.findCacheOperations(specificMethod.getDeclaringClass());
if (opDef != null && ClassUtils.isUserLevelMethod(method)) {
return opDef;
} else {
//前面没有找到的话,则从原始执行方法上去找
if (specificMethod != method) {
opDef = this.findCacheOperations(method);
if (opDef != null) {
return opDef;
}
//从原始执行方法的类上去找
opDef = this.findCacheOperations(method.getDeclaringClass());
if (opDef != null && ClassUtils.isUserLevelMethod(method)) {
return opDef;
}
}

return null;
}
}
}
}
//由子类实现逻辑
@Nullable
protected abstract Collection<CacheOperation> findCacheOperations(Class<?> var1);
//由子类实现逻辑
@Nullable
protected abstract Collection<CacheOperation> findCacheOperations(Method var1);

}

4.总结

本章本章主要从SpringCache 缓存注解的解析工作入手分析,主要的关键点如下:
(1)Spring cache提供了一个缓存注解解析类,专门负责解析类或者方法层次上面注解
(2)解析的过程将注解信息封装成CacheOperation的对象中,由此方面操作。
(3)提供了一个缓存操作资源类(CacheOperationSource)负责管控缓存注解的解析过程。只需将这个缓存操作资源置入想要的地方,就能在需要的地方完成缓存注解解析,提供了一个缓存信息的操作对象。