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) { SpringCacheAnnotationParser.DefaultCacheConfig defaultConfig = this .getDefaultCacheConfig(type); 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 annotation = (CacheConfig)AnnotatedElementUtils.findMergedAnnotation(target, CacheConfig.class); 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 ; 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)); } } 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)); } } 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)); } } 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(); 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操作的基本属性,是对缓存信息的抽象
CacheableOperation(@Cacheable)
CachePutOperation(@CachePut)
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 { private final boolean publicMethodsOnly; private final Set<CacheAnnotationParser> annotationParsers; @Nullable protected Collection<CacheOperation> findCacheOperations (Class<?> clazz) { return this .determineCacheOperations((parser) -> { return parser.parseCacheAnnotations(clazz); }); } @Nullable protected Collection<CacheOperation> findCacheOperations (Method method) { return this .determineCacheOperations((parser) -> { return parser.parseCacheAnnotations(method); }); } @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; } @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(); 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 { Object cacheKey = this .getCacheKey(method, targetClass); Collection<CacheOperation> cached = (Collection)this .attributeCache.get(cacheKey); if (cached != null ) { return cached != NULL_CACHING_ATTRIBUTE ? cached : null ; } else { 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; } } } protected Object getCacheKey (Method method, @Nullable Class<?> targetClass) { return new MethodClassKey(method, targetClass); } @Nullable private Collection<CacheOperation> computeCacheOperations (Method method, @Nullable Class<?> targetClass) { 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 { 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)负责管控缓存注解的解析过程。只需将这个缓存操作资源置入想要的地方,就能在需要的地方完成缓存注解解析,提供了一个缓存信息的操作对象。