相关阅读
简介
声明式缓存管理器的AOP方法拦截器,实现了MethodInterceptor
接口,继承于CacheAspectSupport
;
核心代码
/**
* 实现方法拦截处理逻辑
*/
@Nullable
public Object invoke(final MethodInvocation invocation) throws Throwable {
Method method = invocation.getMethod();
// 以及MethodInvocation生成CacheOperation invoker
CacheOperationInvoker aopAllianceInvoker = () -> {
try {
// 简单调用MethodInvocation的proceed方法
return invocation.proceed();
}
catch (Throwable ex) {
throw new CacheOperationInvoker.ThrowableWrapper(ex);
}
};
// 获取方法所在的实例
Object target = invocation.getThis();
Assert.state(target != null, "Target must not be null");
try {
// 调用CacheAspectSupport的方法完成缓存逻辑
return execute(aopAllianceInvoker, target, method, invocation.getArguments());
}
catch (CacheOperationInvoker.ThrowableWrapper th) {
throw th.getOriginal();
}
}
继承关系
public abstract class AbstractCacheInvoker
public abstract class CacheAspectSupport extends AbstractCacheInvoker implements BeanFactoryAware, InitializingBean, SmartInitializingSingleton
public class CacheInterceptor extends CacheAspectSupport implements MethodInterceptor, Serializable
AbstractCacheInvoker
简介
调用缓存方法的基础组件,并且由可配置的CacheErrorHandler
处理调用过程层中发生的异常;
核心代码
// 异常处理器
protected SingletonSupplier<CacheErrorHandler> errorHandler;
/**
* 构造方法
*/
protected AbstractCacheInvoker() {
// 异常处理器默认为SimpleCacheErrorHandler
this.errorHandler = SingletonSupplier.of(SimpleCacheErrorHandler::new);
}
/**
* 获取缓存值
*/
@Nullable
protected Cache.ValueWrapper doGet(Cache cache, Object key) {
try {
return cache.get(key);
}
catch (RuntimeException ex) {
// 处理异常并返回null
getErrorHandler().handleCacheGetError(ex, cache, key);
return null; // If the exception is handled, return a cache miss
}
}
/**
* 存入缓存值
*/
protected void doPut(Cache cache, Object key, @Nullable Object result) {
try {
cache.put(key, result);
}
catch (RuntimeException ex) {
getErrorHandler().handleCachePutError(ex, cache, key, result);
}
}
/**
* 清除缓存值
*/
protected void doEvict(Cache cache, Object key, boolean immediate) {
try {
if (immediate) {
// 立即清除,后续不可见
cache.evictIfPresent(key);
}
else {
cache.evict(key);
}
}
catch (RuntimeException ex) {
getErrorHandler().handleCacheEvictError(ex, cache, key);
}
}
/**
* 清空缓存
*/
protected void doClear(Cache cache, boolean immediate) {
try {
if (immediate) {
// 立即清除,后续不可见
cache.invalidate();
}
else {
cache.clear();
}
}
catch (RuntimeException ex) {
getErrorHandler().handleCacheClearError(ex, cache);
}
}
CacheAspectSupport
简介
缓存切面的基础类,支持Spring基础Cache
框架;
使用模版模式定义了缓存切面处理流程;
核心代码
// 缓存动作元数据
private final Map<CacheOperationCacheKey, CacheOperationMetadata> metadataCache = new ConcurrentHashMap<>(1024);
// 缓存动作表达式解析器
private final CacheOperationExpressionEvaluator evaluator = new CacheOperationExpressionEvaluator();
// 缓存动作解析器
@Nullable
private CacheOperationSource cacheOperationSource;
// 缓存KEY生成器
private SingletonSupplier<KeyGenerator> keyGenerator = SingletonSupplier.of(SimpleKeyGenerator::new);
// 缓存解析器
@Nullable
private SingletonSupplier<CacheResolver> cacheResolver;
// Bean工厂
@Nullable
private BeanFactory beanFactory;
// 初始化标识
private boolean initialized = false;
/**
* 配置
*/
public void configure(
@Nullable Supplier<CacheErrorHandler> errorHandler, @Nullable Supplier<KeyGenerator> keyGenerator,
@Nullable Supplier<CacheResolver> cacheResolver, @Nullable Supplier<CacheManager> cacheManager) {
this.errorHandler = new SingletonSupplier<>(errorHandler, SimpleCacheErrorHandler::new);
this.keyGenerator = new SingletonSupplier<>(keyGenerator, SimpleKeyGenerator::new);
this.cacheResolver = new SingletonSupplier<>(cacheResolver,
() -> SimpleCacheResolver.of(SupplierUtils.resolve(cacheManager)));
}
/**
* 执行
*/
@Nullable
protected Object execute(CacheOperationInvoker invoker, Object target, Method method, Object[] args) {
// 初始化完成,已准备好
// Check whether aspect is enabled (to cope with cases where the AJ is pulled in automatically)
if (this.initialized) {
// 获取最终class类型
Class<?> targetClass = getTargetClass(target);
CacheOperationSource cacheOperationSource = getCacheOperationSource();
// 缓存动作解析器存在
if (cacheOperationSource != null) {
// 解析本方法上的缓存动作
Collection<CacheOperation> operations = cacheOperationSource.getCacheOperations(method, targetClass);
if (!CollectionUtils.isEmpty(operations)) {
// 最终执行方法
return execute(invoker, method,
new CacheOperationContexts(operations, method, args, target, targetClass));
}
}
}
return invoker.invoke();
}
/**
* 执行
*/
@Nullable
private Object execute(final CacheOperationInvoker invoker, Method method, CacheOperationContexts contexts) {
// 针对同步的缓存动作做特殊处理
// Special handling of synchronized invocation
if (contexts.isSynchronized()) {
CacheOperationContext context = contexts.get(CacheableOperation.class).iterator().next();
if (isConditionPassing(context, CacheOperationExpressionEvaluator.NO_RESULT)) {
Object key = generateKey(context, CacheOperationExpressionEvaluator.NO_RESULT);
Cache cache = context.getCaches().iterator().next();
try {
return wrapCacheValue(method, handleSynchronizedGet(invoker, key, cache));
}
catch (Cache.ValueRetrievalException ex) {
// Directly propagate ThrowableWrapper from the invoker,
// or potentially also an IllegalArgumentException etc.
ReflectionUtils.rethrowRuntimeException(ex.getCause());
}
}
else {
// 无缓存动作,直接执行原方法
// No caching required, only call the underlying method
return invokeOperation(invoker);
}
}
// 处理发生在方法执行前的CacheEvict动作
// Process any early evictions
processCacheEvicts(contexts.get(CacheEvictOperation.class), true,
CacheOperationExpressionEvaluator.NO_RESULT);
// 判断是否命中一个缓存值
// Check if we have a cached item matching the conditions
Cache.ValueWrapper cacheHit = findCachedItem(contexts.get(CacheableOperation.class));
// Collect puts from any @Cacheable miss, if no cached item is found
List<CachePutRequest> cachePutRequests = new ArrayList<>();
if (cacheHit == null) {
// 如果没有命中缓存,Cacheable需要将方法返回值放入缓存,即CachePut
collectPutRequests(contexts.get(CacheableOperation.class),
CacheOperationExpressionEvaluator.NO_RESULT, cachePutRequests);
}
// 缓存值
Object cacheValue;
// 方法返回值
Object returnValue;
// 如果命中缓存且不需要执行CachePut动作,则直接使用缓存值
if (cacheHit != null && !hasCachePut(contexts)) {
// If there are no put requests, just use the cache hit
cacheValue = cacheHit.get();
returnValue = wrapCacheValue(method, cacheValue);
}
else {
// 执行方法获取返回值并重新生成缓存值
// Invoke the method if we don't have a cache hit
returnValue = invokeOperation(invoker);
cacheValue = unwrapReturnValue(returnValue);
}
// 收集CachePut动作,与未命中缓存值的Cacheable动作合一
// Collect any explicit @CachePuts
collectPutRequests(contexts.get(CachePutOperation.class), cacheValue, cachePutRequests);
// 处理put动作
// Process any collected put requests, either from @CachePut or a @Cacheable miss
for (CachePutRequest cachePutRequest : cachePutRequests) {
cachePutRequest.apply(cacheValue);
}
// 处理发生在方法执行后的CacheEvict动作
// Process any late evictions
processCacheEvicts(contexts.get(CacheEvictOperation.class), false, cacheValue);
return returnValue;
}
/**
* 处理CacheEvict注解
*/
private void processCacheEvicts(
Collection<CacheOperationContext> contexts, boolean beforeInvocation, @Nullable Object result) {
// 遍历CacheEvict动作
for (CacheOperationContext context : contexts) {
CacheEvictOperation operation = (CacheEvictOperation) context.metadata.operation;
if (beforeInvocation == operation.isBeforeInvocation() && isConditionPassing(context, result)) {
performCacheEvict(context, operation, result);
}
}
}
/**
* 执行CacheEvict动作
*/
private void performCacheEvict(
CacheOperationContext context, CacheEvictOperation operation, @Nullable Object result) {
Object key = null;
// 遍历cache动作上下文的所有缓存
for (Cache cache : context.getCaches()) {
// 缓存是否全部清除
if (operation.isCacheWide()) {
logInvalidating(context, operation, null);
doClear(cache);
}
else {
if (key == null) {
key = generateKey(context, result);
}
logInvalidating(context, operation, key);
// 请求单个缓存KEY
doEvict(cache, key);
}
}
}
/**
* 从允许执行的Cacheable动作中找到一个存在的缓存值
*/
@Nullable
private Cache.ValueWrapper findCachedItem(Collection<CacheOperationContext> contexts) {
Object result = CacheOperationExpressionEvaluator.NO_RESULT;
// 遍历Cacheable动作
for (CacheOperationContext context : contexts) {
// 允许执行
if (isConditionPassing(context, result)) {
Object key = generateKey(context, result);
// 查找缓存值
Cache.ValueWrapper cached = findInCaches(context, key);
if (cached != null) {
// 命中缓存就返回
return cached;
}
else {
if (logger.isTraceEnabled()) {
logger.trace("No cache entry for key '" + key + "' in cache(s) " + context.getCacheNames());
}
}
}
}
return null;
}
/**
* 从缓存动作上下文查找缓存值
*/
@Nullable
private Cache.ValueWrapper findInCaches(CacheOperationContext context, Object key) {
// 遍历缓存
for (Cache cache : context.getCaches()) {
// 查找指定缓存KEY
Cache.ValueWrapper wrapper = doGet(cache, key);
if (wrapper != null) {
if (logger.isTraceEnabled()) {
logger.trace("Cache entry for key '" + key + "' found in cache '" + cache.getName() + "'");
}
return wrapper;
}
}
return null;
}
/**
* 收集CachePut动作
*/
private void collectPutRequests(Collection<CacheOperationContext> contexts,
@Nullable Object result, Collection<CachePutRequest> putRequests) {
// 遍历cache动作
for (CacheOperationContext context : contexts) {
// 允许执行
if (isConditionPassing(context, result)) {
Object key = generateKey(context, result);
// Cacheable类似于CachePut
putRequests.add(new CachePutRequest(context, key));
}
}
}
/**
* 是否需要执行CachePut动作
*/
private boolean hasCachePut(CacheOperationContexts contexts) {
// Evaluate the conditions *without* the result object because we don't have it yet…
// 获取CachePut动作
Collection<CacheOperationContext> cachePutContexts = contexts.get(CachePutOperation.class);
Collection<CacheOperationContext> excluded = new ArrayList<>();
// 遍历所有CachePut动作
for (CacheOperationContext context : cachePutContexts) {
try {
if (!context.isConditionPassing(CacheOperationExpressionEvaluator.RESULT_UNAVAILABLE)) {
// 无法执行的CachePut动作
excluded.add(context);
}
}
catch (VariableNotAvailableException ex) {
// Ignoring failure due to missing result, consider the cache put has to proceed
}
}
// 是否有需要执行的CachePut动作
// Check if all puts have been excluded by condition
return (cachePutContexts.size() != excluded.size());
}
/**
* 缓存动作上下文
* 内部类
*/
protected class CacheOperationContext implements CacheOperationInvocationContext<CacheOperation> {
// 缓存动作元数据
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;
/**
* cache注解的condition是否满足
*/
protected boolean isConditionPassing(@Nullable Object result) {
// 如果还未判断过,则进行判断;否则直接使用
if (this.conditionPassing == null) {
// condition属性不存在则默认为true
if (StringUtils.hasText(this.metadata.operation.getCondition())) {
// 根据result得出评估上下文
EvaluationContext evaluationContext = createEvaluationContext(result);
// 得出结论
this.conditionPassing = evaluator.condition(this.metadata.operation.getCondition(),
this.metadata.methodKey, evaluationContext);
}
else {
this.conditionPassing = true;
}
}
return this.conditionPassing;
}
/**
* 是否可以存入缓存
*/
protected boolean canPutToCache(@Nullable Object value) {
String unless = "";
// Cacheable注解
if (this.metadata.operation instanceof CacheableOperation) {
unless = ((CacheableOperation) this.metadata.operation).getUnless();
}
// CachePut注解
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;
}
}
/**
* 缓存动作上下文管理器
* 内部类
*/
private class CacheOperationContexts {
// cache动作上下文集合
private final MultiValueMap<Class<? extends CacheOperation>, CacheOperationContext> contexts;
// 同步标识
private final boolean sync;
/**
* 构造方法
* 集中管理CacheOperationSource解析出来的CacheOperation
*/
public CacheOperationContexts(Collection<? extends CacheOperation> operations, Method method,
Object[] args, Object target, Class<?> targetClass) {
// 遍历cache operation集合
this.contexts = new LinkedMultiValueMap<>(operations.size());
for (CacheOperation op : operations) {
// 添加cache operation上下文
this.contexts.add(op.getClass(), getOperationContext(op, method, args, target, targetClass));
}
this.sync = determineSyncFlag(method);
}
/**
* 获取某CacheOperation的所有上下文信息
*/
public Collection<CacheOperationContext> get(Class<? extends CacheOperation> operationClass) {
Collection<CacheOperationContext> result = this.contexts.get(operationClass);
return (result != null ? result : Collections.emptyList());
}
}
/**
* 缓存动作的元数据
* 内部类
*/
protected static class CacheOperationMetadata {
// 缓存动作
private final CacheOperation operation;
// 方法
private final Method method;
// 目标类对象
private final Class<?> targetClass;
// 目标方法
private final Method targetMethod;
// 注解元素KEY
private final AnnotatedElementKey methodKey;
// 缓存KEY生成器
private final KeyGenerator keyGenerator;
// 缓存解析器
private final CacheResolver cacheResolver;
/**
* 构造方法
*/
public CacheOperationMetadata(CacheOperation operation, Method method, Class<?> targetClass,
KeyGenerator keyGenerator, CacheResolver cacheResolver) {
// 存储缓存动作的参数
this.operation = operation;
this.method = BridgeMethodResolver.findBridgedMethod(method);
this.targetClass = targetClass;
this.targetMethod = (!Proxy.isProxyClass(targetClass) ?
AopUtils.getMostSpecificMethod(method, targetClass) : this.method);
this.methodKey = new AnnotatedElementKey(this.targetMethod, targetClass);
this.keyGenerator = keyGenerator;
this.cacheResolver = cacheResolver;
}
}
/**
* CachePut动作
* 内部类
*/
private class CachePutRequest {
// 缓存动作上下文
private final CacheOperationContext context;
// 缓存KEY
private final Object key;
/**
* 执行CachePut动作
*/
public void apply(@Nullable Object result) {
// 可以执行PUT动作
if (this.context.canPutToCache(result)) {
for (Cache cache : this.context.getCaches()) {
// 将结果存入缓存
doPut(cache, this.key, result);
}
}
}
}
/**
* 缓存动作KEY
* 内部类
*/
private static final class CacheOperationCacheKey implements Comparable<CacheOperationCacheKey> {
// 缓存动作
private final CacheOperation cacheOperation;
// 注解元素KEY
private final AnnotatedElementKey methodCacheKey;
/**
* 比较
*/
@Override
public int compareTo(CacheOperationCacheKey other) {
int result = this.cacheOperation.getName().compareTo(other.cacheOperation.getName());
if (result == 0) {
result = this.methodCacheKey.compareTo(other.methodCacheKey);
}
return result;
}
}