@cachable中cacheNames和Key之间的区别

时间:2016-08-19 16:16:58

标签: spring caching hashmap

我是缓存和Spring的新手,我无法解决以下来自Spring Docs的示例中cacheNames和Key之间的区别:

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

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

我说高速缓存是否存储为如下关键值:

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

提前致谢。

3 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

cacheNames的一个重要意义是可以帮助在未将显式键传递给方法时使用@Cacheable的默认键生成。对于使用Spring Cache时未在类级别或方法级别提供cacheNames的人来说,从Spring文档中还不清楚什么是严重错误或不正确的。

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

答案 2 :(得分:0)

CacheName 更像是一组缓存键。当你打开这个类 org.springframework.cache.interceptor.AbstractCacheResolver 你会发现这个方法可以通过cache

找到cacheName
@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