缓存切面:【通知+目标方法调用】

缓存操作执行过程:
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 缓存切面的更多相关文章

  1. Redis+Spring缓存实例

    转自:小宝鸽 一.Redis了解 1.1.Redis介绍: redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).lis ...

  2. Redis+Spring缓存实例(windows环境,附实例源码及详解)

    原文出处: 小宝鸽 一.Redis了解 1.1.Redis介绍: redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串). ...

  3. Spring – 缓存注解

    Spring缓存抽象概述 Spring框架自身并没有实现缓存解决方案,但是从3.1开始定义了org.springframework.cache.Cache和org.springframework.ca ...

  4. 以Spring整合EhCache为例从根本上了解Spring缓存这件事(转)

    前两节"Spring缓存抽象"和"基于注解驱动的缓存"是为了更加清晰的了解Spring缓存机制,整合任何一个缓存实现或者叫缓存供应商都应该了解并清楚前两节,如果 ...

  5. Spring缓存机制的理解

    在spring缓存机制中,包括了两个方面的缓存操作:1.缓存某个方法返回的结果:2.在某个方法执行前或后清空缓存. 下面写两个类来模拟Spring的缓存机制: package com.sin90lzc ...

  6. 【Java EE 学习 78 上】【数据采集系统第十天】【Service使用Spring缓存模块】

    一.需求分析 调查问卷中或许每一个单击动作都会引发大量的数据库访问,特别是在参与调查的过程中,只是单击“上一页”或者“下一页”的按钮就会引发大量的查询,必须对这种问题进行优化才行.使用缓存策略进行查询 ...

  7. Spring缓存框架原理浅谈

    运维在上线,无聊写博客.最近看了下Spring的缓存框架,这里写一下 1.Spring 缓存框架 原理浅谈 2.Spring 缓存框架 注解使用说明 3.Spring 缓存配置 + Ehcache(默 ...

  8. Spring4.1新特性——Spring缓存框架增强(转)

    目录 Spring4.1新特性——综述 Spring4.1新特性——Spring核心部分及其他 Spring4.1新特性——Spring缓存框架增强 Spring4.1新特性——异步调用和事件机制的异 ...

  9. 使用Spring缓存的简单Demo

    使用Spring缓存的简单Demo 1. 首先创建Maven工程,在Pom中配置 <dependency> <groupId>org.springframework</g ...

随机推荐

  1. Linux下安装升级python

    本文主要是参考帖子,感谢这位博主,我主要是对相关操作进行补充和说明. 本文主要是在linux(centos)下安装Python3.7.1 1.下载安装Python-3.7.1 1) 下载Python- ...

  2. linux c 链接详解3-静态库

    3静态库 摘自:Linux C编程一站式学习 透过本节可以学会编译静态链接库的shell脚本! 有时候需要把一组代码编译成一个库,这个库在很多项目中都要用到,例如libc就是这样一个库,我们在不同的程 ...

  3. Python控制语句执行流程

    if语句: if<条件>:#条件之后必须有“:”.  <语句> if语句的三元运算符: <表达式1>if<条件>else<表达式2>:其语义 ...

  4. web部署命令简单记录

    非 root 用户设置环境变量:在< .bash_profile >中设置 后台运行:nohup dosomething >> log.out & nginx 启动ng ...

  5. 《Head First 软件开发》阅读一

    伟大的软件开发:让客户满意. 大多数项目的焦点:钱.时间. 我们需要交付的软件系统是需要客户满意,而你认为的完成并不是客户认为的完成. 如果我们不能确定客户需要的是什么,得回去问问他们.这是执行一个项 ...

  6. Maven:mirror和repository

    1 Repository(仓库) 1.1 Maven仓库主要有2种: remote repository:相当于公共的仓库,大家都能访问到,一般可以用URL的形式访问 local repository ...

  7. eclipse中没有server选项无法配置Tomcat

    eclipse集成Tomcat: 打开eclipse - 窗口 - 首选项 - 服务器 - 运行时环境 找到Tomcat然后添加. eclipse添加插件: 开发WEB项目时要集成Tomcat可以并不 ...

  8. js对对象增加删除属性

    1.首选创建一个对象 var a={}; 2.然后对这个对象赋值 a.name='zhouy';console.log(a);var age="age";a[age]=26;con ...

  9. postman-变量

    Variables 什么是变量 变量是一个符号,可以接受不同的值.你可能根据你的项目经验,对其他语言的变量比较熟悉.在postman 的工作原理也是一样的 为什么使用变量 变量允许你在不同的地方重复使 ...

  10. Android中实现双击(多击)事件

    要实现双击,你需要保存第一次点击时的时间,需要使用到变量,之后便是与第二次点击时的时间比较,看时间间隔是否在你设定的时间内(比如500ms). ? 1 2 3 4 5 6 7 8 9 10 11 12 ...