簡體   English   中英

如何告訴Spring緩存不要在@Cacheable注釋中緩存空值

[英]How do I tell Spring cache not to cache null value in @Cacheable annotation

有沒有辦法指定如果方法返回null值,那么不要將結果緩存在這樣的方法的@Cacheable注釋中?

@Cacheable(value="defaultCache", key="#pk")
public Person findPerson(int pk) {
   return getSession.getPerson(pk);
}

更新:以下是去年11月提交的關於緩存空值的JIRA問題,尚未解決: [#SPR-8871] @Cachable條件應允許引用返回值 - Spring Projects問題跟蹤器

Hooray,從Spring 3.2開始,框架允許使用Spring SPEL, unless 關於Cacheable的java doc中的注意事項:

http://static.springsource.org/spring/docs/3.2.x/javadoc-api/org/springframework/cache/annotation/Cacheable.html

public abstract String除非

Spring Expression Language(SpEL)屬性用於否決方法緩存。

與condition()不同,此表達式在調用方法后進行計算,因此可以引用結果。 默認為“”,表示緩存永遠不會被否決。

重要的方面是unless在調用方法之后進行評估。 這非常有意義,因為如果密鑰已經在緩存中,則永遠不會執行該方法。

因此,在上面的示例中,您只需注釋如下(#result可用於測試方法的返回值):

@Cacheable(value="defaultCache", key="#pk", unless="#result == null")
public Person findPerson(int pk) {
   return getSession.getPerson(pk);
}

我想這種情況源於使用可插入緩存實現,如Ehcache,它允許緩存空值。 根據您的使用案例情況,這可能是也可能不是。

更新此答案現已過時,對於Spring 3.2及更高版本,請參閱Tech Trip的答案 ,OP:隨時將其標記為已接受。

我不認為這是可能的(即使Spring中的條件Cache驅逐可以在使用@CacheEvict參數beforeInvocation設置為false的方法調用之后執行,這是默認值)檢查CacheAspectSupport類顯示返回的值不是存儲在inspectAfterCacheEvicts(ops.get(EVICT));之前的任何地方inspectAfterCacheEvicts(ops.get(EVICT)); 呼叫。

protected Object execute(Invoker invoker, Object target, Method method, Object[] args) {
    // check whether aspect is enabled
    // to cope with cases where the AJ is pulled in automatically
    if (!this.initialized) {
        return invoker.invoke();
    }

    // get backing class
    Class<?> targetClass = AopProxyUtils.ultimateTargetClass(target);
    if (targetClass == null && target != null) {
        targetClass = target.getClass();
    }
    final Collection<CacheOperation> cacheOp = getCacheOperationSource().getCacheOperations(method, targetClass);

    // analyze caching information
    if (!CollectionUtils.isEmpty(cacheOp)) {
        Map<String, Collection<CacheOperationContext>> ops = createOperationContext(cacheOp, method, args, target, targetClass);

        // start with evictions
        inspectBeforeCacheEvicts(ops.get(EVICT));

        // follow up with cacheable
        CacheStatus status = inspectCacheables(ops.get(CACHEABLE));

        Object retVal = null;
        Map<CacheOperationContext, Object> updates = inspectCacheUpdates(ops.get(UPDATE));

        if (status != null) {
            if (status.updateRequired) {
                updates.putAll(status.cUpdates);
            }
            // return cached object
            else {
                return status.retVal;
            }
        }

        retVal = invoker.invoke();

        inspectAfterCacheEvicts(ops.get(EVICT));

        if (!updates.isEmpty()) {
            update(updates, retVal);
        }

        return retVal;
    }

    return invoker.invoke();
}

如果是Spring注釋

@Cacheable(value="defaultCache", key="#pk",unless="#result!=null")

不起作用,你可以嘗試:

@CachePut(value="defaultCache", key="#pk",unless="#result==null")

這個對我有用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM