Spring 缓存切面

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

缓存操作执行过程:
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();
        }
    }
}

原文地址:https://www.cnblogs.com/zhuxudong/p/10322611.html

时间: 2024-10-20 10:11:57

Spring 缓存切面的相关文章

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

前两节"Spring缓存抽象"和"基于注解驱动的缓存"是为了更加清晰的了解Spring缓存机制,整合任何一个缓存实现或者叫缓存供应商都应该了解并清楚前两节,如果只是为了快速的应用EhCache到Spring项目中,请直接前往第三节"Spring整合EhCache缓存". 一.   Spring缓存抽象 1.       注意和核心思想 Spring自身并没有实现缓存解决方案,但是对缓存管理功能提供了声明式的支持,能够与多种流行的缓存实现进行集成.

Spring面向切面编程

  1.面向切面编程(AOP)的概念:把项目中需要在多处用到的功能,比如日志.安全和事物等集中到一个类中处理,而不用在每个需要用到该功能的地方显式调用.   2.术语解释:        横切关注点:分布应用于多处的功能        切面:横切关注点可以被模块化为一个类,这个类被称为一个切面        通知(advice):切面要完成的工作.Spring的通知有5种类型:before.after.after-returning.after-throwing和around这五种类型.    

Spring缓存源码剖析:(二)CacheManager

一.CacheManager总览 如果需要Spring缓存可以正常工作,必须配置一个CacheManager. CacheManager实现类你可以配置Spring-context本身提供的SimpleCacheManager和ConcurrentMapCacheManager等.或者使用RedisCacheManager将缓存内容存放到Redis中.下面类图中RedisCacheManager来自于spring-data-redis  jar包中,AbstractTransactionSupp

Spring面向切面 --- AspectJ --- 简单使用

Spring面向切面 --- AspectJ --- 简单使用 昨天回复说说的时候突然写下了下面的一段话:分享一下: <!--******************************************* 其实经过的记忆是可以进行道德化的篡改的,就像夏目漱石的<我是猫>:但是不管怎么改,真正的事实是由每一个人的碎片拼起来的:经济学里计算成本的是在计算将来的成本而不是过去的成本,就像动漫<未来日记>一样:过去发生的事情总是在影响着将来,但是过去发生的事情却不能充当将来下

Spring缓存框架原理浅谈

运维在上线,无聊写博客.最近看了下Spring的缓存框架,这里写一下 1.Spring 缓存框架 原理浅谈 2.Spring 缓存框架 注解使用说明 3.Spring 缓存配置 + Ehcache(默认) 4.Spring 缓存配置 + Ehcache(自己实现) 5.Spring 缓存配置 + Memcache 6.Ehcache和Memcache的资料收集 Spring提供的缓存注解,通过对CacheManager管理Cache,实现对缓存的操作.Spring提供的CacheManager和

spring AOP切面日志 拦截方法中有同名方法问题

代码: @ResponseBody @RequestMapping("/login.do") public Json login(SysUserPM sysUserPM, HttpSession session) { Json j = new Json(); SysUserPM sysUser = sysUserServiceI.doLogin(sysUserPM); if (sysUser != null) { System.out.println("后台用户登录成功!&q

基于Ehcache的Spring缓存详解

一 简介 缓存,通过将数据保存在缓冲区中,可以为以后的相同请求提供更快速的查询,同时可以避免方法的多次执行,从而提高应用的性能. 在企业级应用中,为了提升性能,Spring提供了一种可以在方法级别上进行缓存的缓存抽象.通过使用AOP原则,Spring对使用缓存的方法自动生成相应代理类,如果已经为提供的参数执行过该方法,那么就不必重新执行实际方法而是直接返回被缓存的结果.在基于Spring的Web应用中,为了启用缓存功能,需要使用缓存注解对待使用缓存的方法进行标记. Spring缓存仅仅提供了一种

spring缓存Ehcache(入门2)源码解读

Ehcache缓存: 解读: Ehcache缓存是在继承spring缓存核心类CacheManager的基础上实现的. 常用类: EhCacheCacheManager:继承自CacheManager类(org.springframework.cache.CacheManager)负责管理Cache对象. EhCacheManagerFactoryBean:是个工厂类,根据配置文件中设置的参数(配置文件会被注入工厂类对象中),新建Ehcache的CacheManager对象,其可以通过属性con

使用Spring AOP切面解决数据库读写分离

http://blog.jobbole.com/103496/ 为了减轻数据库的压力,一般会使用数据库主从(master/slave)的方式,但是这种方式会给应用程序带来一定的麻烦,比如说,应用程序如何做到把数据写到master库,而读取数据的时候,从slave库读取.如果应用程序判断失误,把数据写入到slave库,会给系统造成致命的打击. 解决读写分离的方案很多,常用的有SQL解析.动态设置数据源.SQL解析主要是通过分析sql语句是insert/select/update/delete中的哪