zoukankan      html  css  js  c++  java
  • 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();
            }
        }
    }
    
  • 相关阅读:
    URAL 1998 The old Padawan 二分
    URAL 1997 Those are not the droids you're looking for 二分图最大匹配
    URAL 1995 Illegal spices 贪心构造
    URAL 1993 This cheeseburger you don't need 模拟题
    URAL 1992 CVS
    URAL 1991 The battle near the swamp 水题
    Codeforces Beta Round #92 (Div. 1 Only) A. Prime Permutation 暴力
    Codeforces Beta Round #7 D. Palindrome Degree hash
    Codeforces Beta Round #7 C. Line Exgcd
    Codeforces Beta Round #7 B. Memory Manager 模拟题
  • 原文地址:https://www.cnblogs.com/zhuxudong/p/10322611.html
Copyright © 2011-2022 走看看