CompositeCacheOperationSource
又是Composite
组合模式,此设计模式在Spring中大量存在。
public class CompositeCacheOperationSource implements CacheOperationSource, Serializable { // 这里用的数组,表面只能赋值一次 并且只能通过构造函数赋值 private final CacheOperationSource[] cacheOperationSources; public CompositeCacheOperationSource(CacheOperationSource... cacheOperationSources) { this.cacheOperationSources = cacheOperationSources; } public final CacheOperationSource[] getCacheOperationSources() { return this.cacheOperationSources; } @Override @Nullable public Collection<CacheOperation> getCacheOperations(Method method, @Nullable Class<?> targetClass) { Collection<CacheOperation> ops = null; for (CacheOperationSource source : this.cacheOperationSources) { Collection<CacheOperation> cacheOperations = source.getCacheOperations(method, targetClass); if (cacheOperations != null) { if (ops == null) { ops = new ArrayList<>(); } ops.addAll(cacheOperations); } } return ops; } }
对它的解释就是,所以组合进取的属性源,最终都会叠加生效。
注意:它还是个抽象类哦~~~它的唯一实现如下(匿名内部类):
public class BeanFactoryCacheOperationSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor { @Nullable private CacheOperationSource cacheOperationSource; private final CacheOperationSourcePointcut pointcut = new CacheOperationSourcePointcut() { @Override @Nullable protected CacheOperationSource getCacheOperationSource() { return cacheOperationSource; } }; ... }
CacheAnnotationParser
:缓存注解解析器
解析Spring三大注解缓存的策略接口~~~
// @since 3.1 public interface CacheAnnotationParser { @Nullable Collection<CacheOperation> parseCacheAnnotations(Class<?> type); @Nullable Collection<CacheOperation> parseCacheAnnotations(Method method); }
Spring内建了一个唯一实现类:SpringCacheAnnotationParser。它对把注解解析为缓存属性非常的重要。
// @since 3.1 public class SpringCacheAnnotationParser implements CacheAnnotationParser, Serializable { private static final Set<Class<? extends Annotation>> CACHE_OPERATION_ANNOTATIONS = new LinkedHashSet<>(8); // 它能处理的注解类型,一目了然 static { CACHE_OPERATION_ANNOTATIONS.add(Cacheable.class); CACHE_OPERATION_ANNOTATIONS.add(CacheEvict.class); CACHE_OPERATION_ANNOTATIONS.add(CachePut.class); CACHE_OPERATION_ANNOTATIONS.add(Caching.class); } // 处理class和Method // 使用DefaultCacheConfig,把它传给parseCacheAnnotations() 来给注解属性搞定默认值 // 至于为何自己要新new一个呢???其实是因为@CacheConfig它只能放在类上呀~~~(传Method也能获取到类) // 返回值都可以为null(没有标注此注解方法、类 那肯定返回null啊) @Override @Nullable public Collection<CacheOperation> parseCacheAnnotations(Class<?> type) { DefaultCacheConfig defaultConfig = new DefaultCacheConfig(type); return parseCacheAnnotations(defaultConfig, type); } @Override @Nullable public Collection<CacheOperation> parseCacheAnnotations(Method method) { DefaultCacheConfig defaultConfig = new DefaultCacheConfig(method.getDeclaringClass()); return parseCacheAnnotations(defaultConfig, method); } // 找到方法/类上的注解们~~~ private Collection<CacheOperation> parseCacheAnnotations(DefaultCacheConfig cachingConfig, AnnotatedElement ae) { // 第三个参数传的false:表示接口的注解它也会看一下~~~ Collection<CacheOperation> ops = parseCacheAnnotations(cachingConfig, ae, false); // 若出现接口方法里也标了,实例方法里也标了,那就继续处理。让以实例方法里标注的为准~~~ if (ops != null && ops.size() > 1) { // More than one operation found -> local declarations override interface-declared ones... Collection<CacheOperation> localOps = parseCacheAnnotations(cachingConfig, ae, true); if (localOps != null) { return localOps; } } return ops; } private Collection<CacheOperation> parseCacheAnnotations(DefaultCacheConfig cachingConfig, AnnotatedElement ae, boolean localOnly) { // localOnly=true,只看自己的不看接口的。false表示接口的也得看~ Collection<? extends Annotation> anns = (localOnly ? AnnotatedElementUtils.getAllMergedAnnotations(ae, CACHE_OPERATION_ANNOTATIONS) : AnnotatedElementUtils.findAllMergedAnnotations(ae, CACHE_OPERATION_ANNOTATIONS)); if (anns.isEmpty()) { return null; } // 这里为和写个1???因为绝大多数情况下,我们都只会标注一个注解~~ final Collection<CacheOperation> ops = new ArrayList<>(1); // 这里的方法parseCacheableAnnotation/parsePutAnnotation等 说白了 就是把注解属性,转换封装成为`CacheOperation`对象~~ // 注意parseCachingAnnotation方法,相当于~把注解属性转换成了CacheOperation对象 下面以它为例介绍 anns.stream().filter(ann -> ann instanceof Cacheable).forEach( ann -> ops.add(parseCacheableAnnotation(ae, cachingConfig, (Cacheable) ann))); anns.stream().filter(ann -> ann instanceof CacheEvict).forEach( ann -> ops.add(parseEvictAnnotation(ae, cachingConfig, (CacheEvict) ann))); anns.stream().filter(ann -> ann instanceof CachePut).forEach( ann -> ops.add(parsePutAnnotation(ae, cachingConfig, (CachePut) ann))); anns.stream().filter(ann -> ann instanceof Caching).forEach( ann -> parseCachingAnnotation(ae, cachingConfig, (Caching) ann, ops)); return ops; } // CacheableOperation是抽象类CacheOperation的子类~ private CacheableOperation parseCacheableAnnotation( AnnotatedElement ae, DefaultCacheConfig defaultConfig, Cacheable cacheable) { // 这个builder是CacheOperation.Builder的子类,父类规定了所有注解通用的一些属性~~~ CacheableOperation.Builder builder = new CacheableOperation.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()); // DefaultCacheConfig是本类的一个内部类,来处理buider,给他赋值默认值~~~ 比如默认的keyGenerator等等 defaultConfig.applyDefault(builder); CacheableOperation op = builder.build(); validateCacheOperation(ae, op); // 校验。key和KeyGenerator至少得有一个 CacheManager和CacheResolver至少得配置一个 return op; } ... // 解析其余注解略,一样的。 // 它其实就是把三三者聚合了,一个一个的遍历。所以它最后一个参数传的ops,在内部进行add private void parseCachingAnnotation(AnnotatedElement ae, DefaultCacheConfig defaultConfig, Caching caching, Collection<CacheOperation> ops) { Cacheable[] cacheables = caching.cacheable(); for (Cacheable cacheable : cacheables) { ops.add(parseCacheableAnnotation(ae, defaultConfig, cacheable)); } CacheEvict[] cacheEvicts = caching.evict(); for (CacheEvict cacheEvict : cacheEvicts) { ops.add(parseEvictAnnotation(ae, defaultConfig, cacheEvict)); } CachePut[] cachePuts = caching.put(); for (CachePut cachePut : cachePuts) { ops.add(parsePutAnnotation(ae, defaultConfig, cachePut)); } } // 设置默认值的私有静态内部类 private static class DefaultCacheConfig { private final Class<?> target; @Nullable private String[] cacheNames; @Nullable private String keyGenerator; @Nullable private String cacheManager; @Nullable private String cacheResolver; private boolean initialized = false; // 唯一构造函数~ public DefaultCacheConfig(Class<?> target) { this.target = target; } public void applyDefault(CacheOperation.Builder builder) { // 如果还没初始化过,就进行初始化(毕竟一个类上有多个方法,这种默认通用设置只需要来一次即可) if (!this.initialized) { // 找到类上、接口上的@CacheConfig注解 它可以指定本类使用的cacheNames和keyGenerator和cacheManager和cacheResolver CacheConfig annotation = AnnotatedElementUtils.findMergedAnnotation(this.target, CacheConfig.class); if (annotation != null) { this.cacheNames = annotation.cacheNames(); this.keyGenerator = annotation.keyGenerator(); this.cacheManager = annotation.cacheManager(); this.cacheResolver = annotation.cacheResolver(); } this.initialized = true; } // 下面方法一句话总结:方法上没有指定的话,就用类上面的CacheConfig配置 if (builder.getCacheNames().isEmpty() && this.cacheNames != null) { builder.setCacheNames(this.cacheNames); } if (!StringUtils.hasText(builder.getKey()) && !StringUtils.hasText(builder.getKeyGenerator()) && StringUtils.hasText(this.keyGenerator)) { builder.setKeyGenerator(this.keyGenerator); } if (StringUtils.hasText(builder.getCacheManager()) || StringUtils.hasText(builder.getCacheResolver())) { // One of these is set so we should not inherit anything } else if (StringUtils.hasText(this.cacheResolver)) { builder.setCacheResolver(this.cacheResolver); } else if (StringUtils.hasText(this.cacheManager)) { builder.setCacheManager(this.cacheManager); } } } }
经过这一番解析后,三大缓存注解,最终都被收集到CacheOperation
里来了,这也就和CacheOperationSource
缓存属性源接口的功能照应了起来。
CacheOperationInvocationContext:执行上下文
它代表缓存执行时的上下文。
//@since 4.1 注意泛型O extends BasicOperation public interface CacheOperationInvocationContext<O extends BasicOperation> { // 缓存操作属性CacheOperation O getOperation(); // 目标类、目标方法 Object getTarget(); Method getMethod(); // 方法入参们 Object[] getArgs(); }
它只有一个CacheAspectSupport内部类实现CacheOperationContext,此处也搬上来吧:
protected class CacheOperationContext implements CacheOperationInvocationContext<CacheOperation> { // 它里面包含了CacheOperation、Method、Class、Method targetMethod;(注意有两个Method)、AnnotatedElementKey、KeyGenerator、CacheResolver等属性 // this.method = BridgeMethodResolver.findBridgedMethod(method); // this.targetMethod = (!Proxy.isProxyClass(targetClass) ? AopUtils.getMostSpecificMethod(method, targetClass) : this.method); // this.methodKey = new AnnotatedElementKey(this.targetMethod, targetClass); private final CacheOperationMetadata metadata; private final Object[] args; private final Object target; private final Collection<? extends Cache> caches; private final Collection<String> cacheNames; @Nullable private Boolean conditionPassing; // 标志CacheOperation.conditon是否是true:表示通过 false表示未通过 public CacheOperationContext(CacheOperationMetadata metadata, Object[] args, Object target) { this.metadata = metadata; this.args = extractArgs(metadata.method, args); this.target = target; // 这里方法里调用了cacheResolver.resolveCaches(context)方法来得到缓存们~~~~ CacheResolver this.caches = CacheAspectSupport.this.getCaches(this, metadata.cacheResolver); // 从caches拿到他们的names们 this.cacheNames = createCacheNames(this.caches); } ... // 省略get/set protected boolean isConditionPassing(@Nullable Object result) { if (this.conditionPassing == null) { // 如果配置了并且还没被解析过,此处就解析condition条件~~~ if (StringUtils.hasText(this.metadata.operation.getCondition())) { // 执行上下文:此处就不得不提一个非常重要的它了:CacheOperationExpressionEvaluator // 它代表着缓存操作中SpEL的执行上下文~~~ 具体可以先参与下面的对它的介绍 // 解析conditon~ EvaluationContext evaluationContext = createEvaluationContext(result); this.conditionPassing = evaluator.condition(this.metadata.operation.getCondition(), this.metadata.methodKey, evaluationContext); } else { this.conditionPassing = true; } } return this.conditionPassing; } // 解析CacheableOperation和CachePutOperation好的unless protected boolean canPutToCache(@Nullable Object value) { String unless = ""; if (this.metadata.operation instanceof CacheableOperation) { unless = ((CacheableOperation) this.metadata.operation).getUnless(); } else if (this.metadata.operation instanceof CachePutOperation) { unless = ((CachePutOperation) this.metadata.operation).getUnless(); } if (StringUtils.hasText(unless)) { EvaluationContext evaluationContext = createEvaluationContext(value); return !evaluator.unless(unless, this.metadata.methodKey, evaluationContext); } return true; } // 这里注意:生成key 需要注意步骤。 // 若配置了key(非空串):那就作为SpEL解析出来 // 否则走keyGenerator去生成~~~(所以你会发现,即使咱们没有配置key和keyGenerator,程序依旧能正常work,只是生成的key很长而已~~~) // (keyGenerator你可以能没配置????) // 若你自己没有手动指定过KeyGenerator,那会使用默认的SimpleKeyGenerator 它的实现比较简单 // 其实若我们自定义KeyGenerator,我觉得可以继承自`SimpleKeyGenerator `,而不是直接实现接口~~~ @Nullable protected Object generateKey(@Nullable Object result) { if (StringUtils.hasText(this.metadata.operation.getKey())) { EvaluationContext evaluationContext = createEvaluationContext(result); return evaluator.key(this.metadata.operation.getKey(), this.metadata.methodKey, evaluationContext); } // key的优先级第一位,没有指定采用生成器去生成~ return this.metadata.keyGenerator.generate(this.target, this.metadata.method, this.args); } private EvaluationContext createEvaluationContext(@Nullable Object result) { return evaluator.createEvaluationContext(this.caches, this.metadata.method, this.args, this.target, this.metadata.targetClass, this.metadata.targetMethod, result, beanFactory); } ... }
CacheOperationExpressionEvaluator:缓存操作执行器
在这之前,在讲解发布订阅、事件机制的文章中:
【小家Spring】从Spring中的(ApplicationEvent)事件驱动机制出发,聊聊【观察者模式】【监听者模式】【发布订阅模式】【消息队列MQ】【EventSourcing】…
讲到过EventExpressionEvaluator,它在解析@EventListener注解的condition属性的时候被使用到,它也继承自抽象父类CachedExpressionEvaluator:
可见本类也是抽象父类的一个实现,是不是顿时有种熟悉感了?
// @since 3.1 注意抽象父类CachedExpressionEvaluator在Spring4.2才有 // CachedExpressionEvaluator里默认使用的解析器是:SpelExpressionParser 以及 // 还准备了一个ParameterNameDiscoverer 可以交给执行上文CacheEvaluationContext使用 class CacheOperationExpressionEvaluator extends CachedExpressionEvaluator { // 注意这两个属性是public的 在CacheAspectSupport里都有使用~~~ public static final Object NO_RESULT = new Object(); public static final Object RESULT_UNAVAILABLE = new Object(); public static final String RESULT_VARIABLE = "result"; private final Map<ExpressionKey, Expression> keyCache = new ConcurrentHashMap<>(64); private final Map<ExpressionKey, Expression> conditionCache = new ConcurrentHashMap<>(64); private final Map<ExpressionKey, Expression> unlessCache = new ConcurrentHashMap<>(64); // 这个方法是创建执行上下文。能给解释:为何可以使用#result这个key的原因 // 此方法的入参确实不少:8个 public EvaluationContext createEvaluationContext(Collection<? extends Cache> caches, Method method, Object[] args, Object target, Class<?> targetClass, Method targetMethod, @Nullable Object result, @Nullable BeanFactory beanFactory) { // root对象,此对象的属性决定了你的#root能够取值的范围,具体下面有贴出此类~ CacheExpressionRootObject rootObject = new CacheExpressionRootObject(caches, method, args, target, targetClass); // 它继承自MethodBasedEvaluationContext,已经讲解过了,本文就不继续深究了~ CacheEvaluationContext evaluationContext = new CacheEvaluationContext(rootObject, targetMethod, args, getParameterNameDiscoverer()); if (result == RESULT_UNAVAILABLE) { evaluationContext.addUnavailableVariable(RESULT_VARIABLE); } else if (result != NO_RESULT) { // 这一句话就是为何我们可以使用#result的核心原因~ evaluationContext.setVariable(RESULT_VARIABLE, result); } // 从这里可知,缓存注解里也是可以使用容器内的Bean的~ if (beanFactory != null) { evaluationContext.setBeanResolver(new BeanFactoryResolver(beanFactory)); } return evaluationContext; } // 都有缓存效果哦,因为都继承自抽象父类CachedExpressionEvaluator嘛 // 抽象父类@since 4.2才出来,就是给解析过程提供了缓存的效果~~~~(注意此缓存非彼缓存) // 解析key的SpEL表达式 @Nullable public Object key(String keyExpression, AnnotatedElementKey methodKey, EvaluationContext evalContext) { return getExpression(this.keyCache, methodKey, keyExpression).getValue(evalContext); } // condition和unless的解析结果若不是bool类型,统一按照false处理~~~~ public boolean condition(String conditionExpression, AnnotatedElementKey methodKey, EvaluationContext evalContext) { return (Boolean.TRUE.equals(getExpression(this.conditionCache, methodKey, conditionExpression).getValue(evalContext, Boolean.class))); } public boolean unless(String unlessExpression, AnnotatedElementKey methodKey, EvaluationContext evalContext) { return (Boolean.TRUE.equals(getExpression(this.unlessCache, methodKey, unlessExpression).getValue(evalContext, Boolean.class))); } /** * Clear all caches. */ void clear() { this.keyCache.clear(); this.conditionCache.clear(); this.unlessCache.clear(); } } // #root可取的值,参考CacheExpressionRootObject这个对象的属性 // @since 3.1 class CacheExpressionRootObject { // 可见#root.caches竟然都是阔仪的~~~ private final Collection<? extends Cache> caches; private final Method method; private final Object[] args; private final Object target; private final Class<?> targetClass; // 省略所有的get/set(其实只有get方法) }
缓存操作的执行器,能让你深刻的理解到#root
、#result
的使用,并且永远忘记不了了。
CacheResolver
其名字已经暗示了其是Cache
解析器,用于根据实际情况来动态解析使用哪个Cache
,它是Spring4.1
提供的新特性。
// @since 4.1 @FunctionalInterface public interface CacheResolver { // 根据执行上下文,拿到最终的缓存Cache集合 // CacheOperationInvocationContext:执行上下文 Collection<? extends Cache> resolveCaches(CacheOperationInvocationContext<?> context); }
它有一些内置实现如下: