緩存切面:【通知+目標方法調用】
緩存操作執行過程:
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();
}
}
}