【问题标题】:Difference Between cacheNames and Key in @cachable@cachable 中 cacheNames 和 Key 的区别
【发布时间】:2016-08-19 16:16:57
【问题描述】:

我是缓存和 Spring 的新手,我无法在 Spring Docs 的以下示例中找出 cacheNames 和 Key 之间的区别:

@Cacheable(cacheNames="books", key="#isbn")
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)

据我了解,缓存只是存储在内存中的键值对。因此,在上面的示例中,第一次调用时,返回的 Book 值将使用 isbn 参数的值作为键存储在缓存中。在 isbn 值与第一次请求相同的后续调用中,将返回存储在缓存中的 Book。将使用 Key 找到缓存中的这本书。那么什么是cacheNames?

我说缓存存储为这样的键值是否正确:

isbn111111 ---> Book,
isbn122222 ---> Book2,
isbn123333 ---> Book3

提前致谢。

【问题讨论】:

    标签: spring caching hashmap


    【解决方案1】:

    CacheName 更像是一组缓存键。当你打开这门课时 org.springframework.cache.interceptor.AbstractCacheResolver 你会发现这个方法通过cacheName找到cache

    @Override
        public Collection<? extends Cache> resolveCaches(CacheOperationInvocationContext<?> context) {
            Collection<String> cacheNames = getCacheNames(context);
            if (cacheNames == null) {
                return Collections.emptyList();
            }
            Collection<Cache> result = new ArrayList<>(cacheNames.size());
            for (String cacheName : cacheNames) {
                Cache cache = getCacheManager().getCache(cacheName);
                if (cache == null) {
                    throw new IllegalArgumentException("Cannot find cache named '" +
                            cacheName + "' for " + context.getOperation());
                }
                result.add(cache);
            }
            return result;
        }
    

    所以稍后在org.springframework.cache.interceptor.CacheAspectSupport spring 将通过缓存键从cache 对象中获取值

    private Object execute(final CacheOperationInvoker invoker, Method method, CacheOperationContexts contexts) {
            // Special handling of synchronized invocation
            if (contexts.isSynchronized()) {
                CacheOperationContext context = contexts.get(CacheableOperation.class).iterator().next();
                if (isConditionPassing(context, CacheOperationExpressionEvaluator.NO_RESULT)) {
                    Object key = generateKey(context, CacheOperationExpressionEvaluator.NO_RESULT);
                    Cache cache = context.getCaches().iterator().next();
                    try {
                        return wrapCacheValue(method, cache.get(key, () -> unwrapReturnValue(invokeOperation(invoker))));
                    }
                    catch (Cache.ValueRetrievalException ex) {
                        // The invoker wraps any Throwable in a ThrowableWrapper instance so we
                        // can just make sure that one bubbles up the stack.
                        throw (CacheOperationInvoker.ThrowableWrapper) ex.getCause();
                    }
                }
    //...other logic
    

    【讨论】:

      【解决方案2】:

      cacheNames 是存储数据的缓存本身的名称。您可以有多个缓存,例如对于不同的实体类型不同的缓存,或者取决于复制需求等。

      【讨论】:

      • 谢谢 - 密钥用于检索存储在缓存中的值,那么为什么 cacheNames 或具有多个缓存相关?
      【解决方案3】:

      cacheNames 的一个意义是帮助在没有将显式键传递给方法时使用 @Cacheable 的默认键生成。如果在使用 Spring Cache 时未在类级别或方法级别提供 cacheNames,那么 Spring 文档中非常不清楚会出现什么严重错误或不准确。

      https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/cache/annotation/CacheConfig.html#cacheNames--

      【讨论】:

        猜你喜欢
        • 2019-03-24
        • 2011-04-20
        • 1970-01-01
        • 2019-02-13
        • 2015-10-12
        • 1970-01-01
        • 2013-12-02
        • 2021-04-20
        相关资源
        最近更新 更多