Spring 緩存切面
阿新 • • 發佈:2019-01-26
創建 pass creat 緩存註解 zab valid nwr vid iss
緩存切面:【通知+目標方法調用】
緩存操作執行過程: 1)如果是同步調用【sync=true】,則首先嘗試從緩存中讀取數據,讀取到則直接返回; 否則執行目標方法,將結果緩存後返回。 2)如果不是同步調用【sync=false,默認】 2-1)執行 beforeInvocation=true 並滿足條件的 CacheEvict 操作, 2-2)從緩存操作上下文中根據緩存鍵讀取數據【存在 @Cacheable 註解】, 緩存未命中:則收集 @Cacheable 緩存寫入請求,並執行目標方法。 緩存命中且無滿足條件的 CachePut 操作:直接讀取緩存結果【目標方法不會被執行】。 2-3)從 @CachePut 註解上收集顯式的緩存寫入操作。 2-4)執行從 @Cacheable 和 @CachePut 上收集到的緩存寫入操作。 2-5)執行 beforeInvocation=false 並滿足條件的 CacheEvict 操作。 最佳實踐: @CachePut 註解使用在寫入和更新操作上 @Cacheable 註解使用在讀取操作上 @CacheEvict 註解使用在刪除操作上
/** * 執行緩存操作的基礎組件,附加緩存異常處理器 */ public abstract class AbstractCacheInvoker { protected SingletonSupplier<CacheErrorHandler> errorHandler; protected AbstractCacheInvoker() { // 不做任何事情的異常處理器 this.errorHandler = SingletonSupplier.of(SimpleCacheErrorHandler::new); } protected AbstractCacheInvoker(CacheErrorHandler errorHandler) { this.errorHandler = SingletonSupplier.of(errorHandler); } public void setErrorHandler(CacheErrorHandler errorHandler) { this.errorHandler = SingletonSupplier.of(errorHandler); } public CacheErrorHandler getErrorHandler() { return this.errorHandler.obtain(); } /** * 執行緩存 Get 操作 */ @Nullable protected Cache.ValueWrapper doGet(Cache cache, Object key) { try { return cache.get(key); } catch (RuntimeException ex) { getErrorHandler().handleCacheGetError(ex, cache, key); return null; // If the exception is handled, return a cache miss } } /** * 執行緩存 Put 操作 */ protected void doPut(Cache cache, Object key, @Nullable Object result) { try { cache.put(key, result); } catch (RuntimeException ex) { getErrorHandler().handleCachePutError(ex, cache, key, result); } } /** * 執行緩存 Evict 操作 */ protected void doEvict(Cache cache, Object key) { try { cache.evict(key); } catch (RuntimeException ex) { getErrorHandler().handleCacheEvictError(ex, cache, key); } } /** * 執行緩存 Clear 操作 */ protected void doClear(Cache cache) { try { cache.clear(); } catch (RuntimeException ex) { getErrorHandler().handleCacheClearError(ex, cache); } } } /** * 緩存切面的基礎類 */ public abstract class CacheAspectSupport extends AbstractCacheInvoker implements BeanFactoryAware, InitializingBean, SmartInitializingSingleton { protected final Log logger = LogFactory.getLog(getClass()); /** * 緩存操作元數據緩存 */ private final Map<CacheOperationCacheKey, CacheOperationMetadata> metadataCache = new ConcurrentHashMap<>(1024); /** * 緩存操作表達式解析器 */ private final CacheOperationExpressionEvaluator evaluator = new CacheOperationExpressionEvaluator(); /** * 緩存操作源:用於將緩存註解解析為緩存操作 */ @Nullable private CacheOperationSource cacheOperationSource; /** * 單例鍵生成器 Supplier */ private SingletonSupplier<KeyGenerator> keyGenerator = SingletonSupplier.of(SimpleKeyGenerator::new); /** * 單例緩存解析器 Supplier */ @Nullable private SingletonSupplier<CacheResolver> cacheResolver; /** * Bean 工廠【DefaultListableBeanFactory】 */ @Nullable private BeanFactory beanFactory; /** * 切面是否已經初始化 */ private boolean initialized = false; @Override public void afterSingletonsInstantiated() { if (getCacheResolver() == null) { // Lazily initialize cache resolver via default cache manager... Assert.state(beanFactory != null, "CacheResolver or BeanFactory must be set on cache aspect"); try { // 基於緩存管理器創建緩存解析器,並寫入 setCacheManager(beanFactory.getBean(CacheManager.class)); } catch (final NoUniqueBeanDefinitionException ex) { throw new IllegalStateException("No CacheResolver specified, and no unique bean of type " + "CacheManager found. Mark one as primary or declare a specific CacheManager to use."); } catch (final NoSuchBeanDefinitionException ex) { throw new IllegalStateException("No CacheResolver specified, and no bean of type CacheManager found. " + "Register a CacheManager bean or remove the @EnableCaching annotation from your configuration."); } } initialized = true; } /** * 基於緩存操作執行上下文和緩存解析器讀取緩存集合 */ protected Collection<? extends Cache> getCaches( CacheOperationInvocationContext<CacheOperation> context, CacheResolver cacheResolver) { final Collection<? extends Cache> caches = cacheResolver.resolveCaches(context); if (caches.isEmpty()) { throw new IllegalStateException("No cache could be resolved for ‘" + context.getOperation() + "‘ using resolver ‘" + cacheResolver + "‘. At least one cache should be provided per cache operation."); } return caches; } @Nullable protected Object execute(CacheOperationInvoker invoker, Object target, Method method, Object[] args) { // 緩存切面是否啟用 if (initialized) { // 讀取目標類 Class final Class<?> targetClass = getTargetClass(target); // 讀取緩存操作源 final CacheOperationSource cacheOperationSource = getCacheOperationSource(); if (cacheOperationSource != null) { // 讀取目標方法上的所有緩存操作 final 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(); } protected CacheOperationContext getOperationContext( CacheOperation operation, Method method, Object[] args, Object target, Class<?> targetClass) { // 讀取緩存操作元數據 final CacheOperationMetadata metadata = getCacheOperationMetadata(operation, method, targetClass); return new CacheOperationContext(metadata, args, target); } protected CacheOperationMetadata getCacheOperationMetadata( CacheOperation operation, Method method, Class<?> targetClass) { // 緩存操作的緩存鍵 final CacheOperationCacheKey cacheKey = new CacheOperationCacheKey(operation, method, targetClass); // 已經創建過則直接讀取 CacheOperationMetadata metadata = metadataCache.get(cacheKey); if (metadata == null) { KeyGenerator operationKeyGenerator; // 1)緩存操作配置了鍵生成器 if (StringUtils.hasText(operation.getKeyGenerator())) { // 寫入指定 bean 名稱的鍵生成器 operationKeyGenerator = getBean(operation.getKeyGenerator(), KeyGenerator.class); } else { // 寫入 SimpleKeyGenerator operationKeyGenerator = getKeyGenerator(); } CacheResolver operationCacheResolver; // 2)緩存操作配置了緩存解析器 if (StringUtils.hasText(operation.getCacheResolver())) { // 寫入指定 bean 名稱的緩存解析器 operationCacheResolver = getBean(operation.getCacheResolver(), CacheResolver.class); } // 3)緩存操作配置了緩存管理器 else if (StringUtils.hasText(operation.getCacheManager())) { final CacheManager cacheManager = getBean(operation.getCacheManager(), CacheManager.class); // 基於目標緩存管理器創建 SimpleCacheResolver 並寫入 operationCacheResolver = new SimpleCacheResolver(cacheManager); } else { // 寫入默認的 SimpleCacheResolver operationCacheResolver = getCacheResolver(); Assert.state(operationCacheResolver != null, "No CacheResolver/CacheManager set"); } // 創建緩存操作元數據並加入緩存 metadata = new CacheOperationMetadata(operation, method, targetClass, operationKeyGenerator, operationCacheResolver); metadataCache.put(cacheKey, metadata); } return metadata; } protected <T> T getBean(String beanName, Class<T> expectedType) { if (beanFactory == null) { throw new IllegalStateException( "BeanFactory must be set on cache aspect for " + expectedType.getSimpleName() + " retrieval"); } return BeanFactoryAnnotationUtils.qualifiedBeanOfType(beanFactory, expectedType, beanName); } /** * Clear the cached metadata. */ protected void clearMetadataCache() { metadataCache.clear(); evaluator.clear(); } @Nullable protected Object execute(CacheOperationInvoker invoker, Object target, Method method, Object[] args) { // 緩存切面是否啟用 if (initialized) { // 讀取目標類 Class final Class<?> targetClass = getTargetClass(target); // 讀取緩存操作源 final CacheOperationSource cacheOperationSource = getCacheOperationSource(); if (cacheOperationSource != null) { // 讀取目標方法上的所有緩存操作 final 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(); } /** * 執行底層目標方法 */ protected Object invokeOperation(CacheOperationInvoker invoker) { return invoker.invoke(); } private Class<?> getTargetClass(Object target) { return AopProxyUtils.ultimateTargetClass(target); } @Nullable private Object execute(final CacheOperationInvoker invoker, Method method, CacheOperationContexts contexts) { // 1)同步調用的特殊處理 if (contexts.isSynchronized()) { final CacheOperationContext context = contexts.get(CacheableOperation.class).iterator().next(); // 緩存操作條件是否匹配 if (isConditionPassing(context, CacheOperationExpressionEvaluator.NO_RESULT)) { // 計算緩存鍵 final Object key = generateKey(context, CacheOperationExpressionEvaluator.NO_RESULT); // 讀取緩存 final Cache cache = context.getCaches().iterator().next(); try { /** * 如果緩存已經存在,則直接讀取;否則執行目標方法,並將其結果值加入緩存。 * 並將結果值進行封裝 */ return wrapCacheValue(method, cache.get(key, () -> unwrapReturnValue(invokeOperation(invoker)))); } catch (final Cache.ValueRetrievalException ex) { throw (CacheOperationInvoker.ThrowableWrapper) ex.getCause(); } } else { // 緩存操作條件不匹配,則直接調用目標方法 return invokeOperation(invoker); } } /** * 1)處理方法調用前的緩存清除 * 如果指定了 CacheEvictOperation 操作 && beforeInvocation==true && 滿足緩存操作條件,則執行緩存清除 */ processCacheEvicts(contexts.get(CacheEvictOperation.class), true, CacheOperationExpressionEvaluator.NO_RESULT); /** * 2)從緩存操作上下文中,讀取指定緩存鍵相關的條目 */ final Cache.ValueWrapper cacheHit = findCachedItem(contexts.get(CacheableOperation.class)); // 緩存未命中,則收集 @Cacheable 緩存寫入請求【結果變量 result 不可用】 final List<CachePutRequest> cachePutRequests = new LinkedList<>(); if (cacheHit == null) { collectPutRequests(contexts.get(CacheableOperation.class), CacheOperationExpressionEvaluator.NO_RESULT, cachePutRequests); } Object cacheValue; Object returnValue; // 1)命中緩存 if (cacheHit != null && !hasCachePut(contexts)) { // 無 CachePut 操作,則直接使用命中的緩存結果 cacheValue = cacheHit.get(); returnValue = wrapCacheValue(method, cacheValue); } else { // 緩存未命中,則執行目標方法 returnValue = invokeOperation(invoker); cacheValue = unwrapReturnValue(returnValue); } // 收集所有顯式的 @CachePut 操作 collectPutRequests(contexts.get(CachePutOperation.class), cacheValue, cachePutRequests); // 執行從 @CachePut or @Cacheable 收集到的緩存寫入操作 for (final CachePutRequest cachePutRequest : cachePutRequests) { cachePutRequest.apply(cacheValue); } // 執行方法執行後的緩存清除操作 processCacheEvicts(contexts.get(CacheEvictOperation.class), false, cacheValue); return returnValue; } @Nullable private Object wrapCacheValue(Method method, @Nullable Object cacheValue) { // 方法的返回結果為 Optional,則進行封裝 if (method.getReturnType() == Optional.class && (cacheValue == null || cacheValue.getClass() != Optional.class)) { return Optional.ofNullable(cacheValue); } return cacheValue; } @Nullable private Object unwrapReturnValue(Object returnValue) { return ObjectUtils.unwrapOptional(returnValue); } private boolean hasCachePut(CacheOperationContexts contexts) { // 讀取 CachePutOperation 的上下文集合 final Collection<CacheOperationContext> cachePutContexts = contexts.get(CachePutOperation.class); final Collection<CacheOperationContext> excluded = new ArrayList<>(); for (final CacheOperationContext context : cachePutContexts) { try { // 緩存操作條件不匹配,則寫入 excluded if (!context.isConditionPassing(CacheOperationExpressionEvaluator.RESULT_UNAVAILABLE)) { excluded.add(context); } } catch (final VariableNotAvailableException ex) { } } // 檢查所有put是否已按條件排除 return cachePutContexts.size() != excluded.size(); } private void processCacheEvicts( Collection<CacheOperationContext> contexts, boolean beforeInvocation, @Nullable Object result) { for (final CacheOperationContext context : contexts) { final CacheEvictOperation operation = (CacheEvictOperation) context.metadata.operation; // 滿足緩存清除條件,則執行緩存清除 if (beforeInvocation == operation.isBeforeInvocation() && isConditionPassing(context, result)) { performCacheEvict(context, operation, result); } } } private void performCacheEvict( CacheOperationContext context, CacheEvictOperation operation, @Nullable Object result) { Object key = null; for (final Cache cache : context.getCaches()) { // 1)是否清緩存中的所有條目,默認為 false if (operation.isCacheWide()) { logInvalidating(context, operation, null); // 清除緩存中的所有條目 doClear(cache); } else { if (key == null) { // 計算緩存鍵 key = generateKey(context, result); } logInvalidating(context, operation, key); // 清除指定鍵關聯的條目 doEvict(cache, key); } } } private void logInvalidating(CacheOperationContext context, CacheEvictOperation operation, @Nullable Object key) { if (logger.isTraceEnabled()) { logger.trace("Invalidating " + (key != null ? "cache key [" + key + "]" : "entire cache") + " for operation " + operation + " on method " + context.metadata.method); } } @Nullable private Cache.ValueWrapper findCachedItem(Collection<CacheOperationContext> contexts) { final Object result = CacheOperationExpressionEvaluator.NO_RESULT; for (final CacheOperationContext context : contexts) { // 匹配緩存操作條件 if (isConditionPassing(context, result)) { final Object key = generateKey(context, result); // 從緩存中查找值 final 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; } private void collectPutRequests(Collection<CacheOperationContext> contexts, @Nullable Object result, Collection<CachePutRequest> putRequests) { for (final CacheOperationContext context : contexts) { if (isConditionPassing(context, result)) { final Object key = generateKey(context, result); // 添加緩存寫入請求 putRequests.add(new CachePutRequest(context, key)); } } } @Nullable private Cache.ValueWrapper findInCaches(CacheOperationContext context, Object key) { // 讀取所有關聯的緩存實例 for (final Cache cache : context.getCaches()) { /** * 基於緩存鍵讀取值,如果找到則返回【 * 可引入本地緩存+Redis緩存模式,本地緩存優先讀取】 */ final 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; } /** * 緩存操作條件是否匹配 */ private boolean isConditionPassing(CacheOperationContext context, @Nullable Object result) { final boolean passing = context.isConditionPassing(result); if (!passing && logger.isTraceEnabled()) { logger.trace("Cache condition failed on method " + context.metadata.method + " for operation " + context.metadata.operation); } return passing; } /** * 計算緩存鍵 */ private Object generateKey(CacheOperationContext context, @Nullable Object result) { final Object key = context.generateKey(result); if (key == null) { throw new IllegalArgumentException("Null key returned for cache operation (maybe you are " + "using named params on classes without debug info?) " + context.metadata.operation); } if (logger.isTraceEnabled()) { logger.trace("Computed cache key ‘" + key + "‘ for operation " + context.metadata.operation); } return key; } private class CacheOperationContexts { /** * 緩存操作與緩存操作上下文的映射 */ private final MultiValueMap<Class<? extends CacheOperation>, CacheOperationContext> contexts; private final boolean sync; public CacheOperationContexts(Collection<? extends CacheOperation> operations, Method method, Object[] args, Object target, Class<?> targetClass) { contexts = new LinkedMultiValueMap<>(operations.size()); for (final CacheOperation op : operations) { // 寫入映射 contexts.add(op.getClass(), getOperationContext(op, method, args, target, targetClass)); } // 寫入同步執行標識 sync = determineSyncFlag(method); } /** * 讀取指定操作的 CacheOperationContext 集合 */ public Collection<CacheOperationContext> get(Class<? extends CacheOperation> operationClass) { final Collection<CacheOperationContext> result = contexts.get(operationClass); return result != null ? result : Collections.emptyList(); } public boolean isSynchronized() { return sync; } private boolean determineSyncFlag(Method method) { // 1)無 @Cacheable 操作,sync 為 false final List<CacheOperationContext> cacheOperationContexts = contexts.get(CacheableOperation.class); if (cacheOperationContexts == null) { // no @Cacheable operation at all return false; } boolean syncEnabled = false; // 2)至少存在一個 @Cacheable 操作的 sync 標識位為 true,則 sync 為 true for (final CacheOperationContext cacheOperationContext : cacheOperationContexts) { if (((CacheableOperation) cacheOperationContext.getOperation()).isSync()) { syncEnabled = true; break; } } /** * 3)如果 sync 為 true * 不能指定多個緩存操作 * Cacheable 操作不能關聯多個緩存 * 不能指定 unless 條件 */ if (syncEnabled) { if (contexts.size() > 1) { throw new IllegalStateException( "@Cacheable(sync=true) cannot be combined with other cache operations on ‘" + method + "‘"); } if (cacheOperationContexts.size() > 1) { throw new IllegalStateException( "Only one @Cacheable(sync=true) entry is allowed on ‘" + method + "‘"); } final CacheOperationContext cacheOperationContext = cacheOperationContexts.iterator().next(); final CacheableOperation operation = (CacheableOperation) cacheOperationContext.getOperation(); if (cacheOperationContext.getCaches().size() > 1) { throw new IllegalStateException( "@Cacheable(sync=true) only allows a single cache on ‘" + operation + "‘"); } if (StringUtils.hasText(operation.getUnless())) { throw new IllegalStateException( "@Cacheable(sync=true) does not support unless attribute on ‘" + operation + "‘"); } return true; } return false; } } /** * 緩存操作的元數據 */ protected static class CacheOperationMetadata { private final CacheOperation operation; private final Method method; private final Class<?> targetClass; private final Method targetMethod; /** * 封裝了註解元素和目標類型的 AnnotatedElementKey */ private final AnnotatedElementKey methodKey; 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; targetMethod = !Proxy.isProxyClass(targetClass) ? AopUtils.getMostSpecificMethod(method, targetClass) : this.method; methodKey = new AnnotatedElementKey(targetMethod, targetClass); this.keyGenerator = keyGenerator; this.cacheResolver = cacheResolver; } } /** * 緩存操作上下文 */ 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; public CacheOperationContext(CacheOperationMetadata metadata, Object[] args, Object target) { this.metadata = metadata; this.args = extractArgs(metadata.method, args); this.target = target; caches = CacheAspectSupport.this.getCaches(this, metadata.cacheResolver); cacheNames = createCacheNames(caches); } @Override public CacheOperation getOperation() { return metadata.operation; } @Override public Object getTarget() { return target; } @Override public Method getMethod() { return metadata.method; } @Override public Object[] getArgs() { return args; } private Object[] extractArgs(Method method, Object[] args) { if (!method.isVarArgs()) { return args; } final Object[] varArgs = ObjectUtils.toObjectArray(args[args.length - 1]); final Object[] combinedArgs = new Object[args.length - 1 + varArgs.length]; System.arraycopy(args, 0, combinedArgs, 0, args.length - 1); System.arraycopy(varArgs, 0, combinedArgs, args.length - 1, varArgs.length); return combinedArgs; } protected boolean isConditionPassing(@Nullable Object result) { if (conditionPassing == null) { // 1)註解的緩存條件不為空 if (StringUtils.hasText(metadata.operation.getCondition())) { // 創建計算上下文 final EvaluationContext evaluationContext = createEvaluationContext(result); // 基於 CacheOperationExpressionEvaluator 計算目標條件 conditionPassing = evaluator.condition(metadata.operation.getCondition(), metadata.methodKey, evaluationContext); } else { // 2)未指定條件默認匹配 conditionPassing = true; } } return conditionPassing; } /** * unless 條件未指定或為 false 時,才允許將結果加入到緩存中 */ protected boolean canPutToCache(@Nullable Object value) { String unless = ""; // 1)從 CacheableOperation 讀取 unless 條件 if (metadata.operation instanceof CacheableOperation) { unless = ((CacheableOperation) metadata.operation).getUnless(); } // 2)從 CachePutOperation 讀取 unless 條件 else if (metadata.operation instanceof CachePutOperation) { unless = ((CachePutOperation) metadata.operation).getUnless(); } // 如果 unless 條件不為空,則計算其值 if (StringUtils.hasText(unless)) { final EvaluationContext evaluationContext = createEvaluationContext(value); return !evaluator.unless(unless, metadata.methodKey, evaluationContext); } // 未指定,則默認將結果加入緩存中 return true; } /** * Compute the key for the given caching operation. */ @Nullable protected Object generateKey(@Nullable Object result) { // 1)基於指定的 SpEL 表達式解析緩存鍵 if (StringUtils.hasText(metadata.operation.getKey())) { final EvaluationContext evaluationContext = createEvaluationContext(result); return evaluator.key(metadata.operation.getKey(), metadata.methodKey, evaluationContext); } // 2)基於鍵生成器生成緩存鍵 return metadata.keyGenerator.generate(target, metadata.method, args); } private EvaluationContext createEvaluationContext(@Nullable Object result) { return evaluator.createEvaluationContext(caches, metadata.method, args, target, metadata.targetClass, metadata.targetMethod, result, beanFactory); } protected Collection<? extends Cache> getCaches() { return caches; } protected Collection<String> getCacheNames() { return cacheNames; } private Collection<String> createCacheNames(Collection<? extends Cache> caches) { final Collection<String> names = new ArrayList<>(); for (final Cache cache : caches) { names.add(cache.getName()); } return names; } } private class CachePutRequest { /** * 緩存操作上下文 */ private final CacheOperationContext context; /** * 緩存鍵 */ private final Object key; public CachePutRequest(CacheOperationContext context, Object key) { this.context = context; this.key = key; } public void apply(@Nullable Object result) { // 方法執行結果是否需要加入緩存中 if (context.canPutToCache(result)) { // 將結果加入相關的緩存中 for (final Cache cache : context.getCaches()) { doPut(cache, key, result); } } } } private static final class CacheOperationCacheKey implements Comparable<CacheOperationCacheKey> { /** * 緩存操作 */ private final CacheOperation cacheOperation; /** * 註解元素 */ private final AnnotatedElementKey methodCacheKey; private CacheOperationCacheKey(CacheOperation cacheOperation, Method method, Class<?> targetClass) { this.cacheOperation = cacheOperation; methodCacheKey = new AnnotatedElementKey(method, targetClass); } @Override public boolean equals(Object other) { if (this == other) { return true; } if (!(other instanceof CacheOperationCacheKey)) { return false; } final CacheOperationCacheKey otherKey = (CacheOperationCacheKey) other; return cacheOperation.equals(otherKey.cacheOperation) && methodCacheKey.equals(otherKey.methodCacheKey); } @Override public int hashCode() { return cacheOperation.hashCode() * 31 + methodCacheKey.hashCode(); } @Override public String toString() { return cacheOperation + " on " + methodCacheKey; } @Override public int compareTo(CacheOperationCacheKey other) { int result = cacheOperation.getName().compareTo(other.cacheOperation.getName()); if (result == 0) { result = methodCacheKey.compareTo(other.methodCacheKey); } return result; } } } /** * 聲明式緩存管理 MethodInterceptor */ @SuppressWarnings("serial") public class CacheInterceptor extends CacheAspectSupport implements MethodInterceptor, Serializable { @Override @Nullable public Object invoke(final MethodInvocation invocation) throws Throwable { // 讀取目標方法 Method method = invocation.getMethod(); CacheOperationInvoker aopAllianceInvoker = () -> { try { return invocation.proceed(); } catch (Throwable ex) { throw new CacheOperationInvoker.ThrowableWrapper(ex); } }; try { // 執行核心操作 return execute(aopAllianceInvoker, invocation.getThis(), method, invocation.getArguments()); } catch (CacheOperationInvoker.ThrowableWrapper th) { throw th.getOriginal(); } } }
Spring 緩存切面