2012-08-24 52 views
35

有沒有一種方法可以指定如果方法返回空值,那麼不要將結果緩存在像這樣的方法的@Cacheable註解中?如何告訴Spring緩存不要在@Cacheable註釋中緩存空值

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

更新: 這裏是關於緩存空值去年十一月,至今尚未解決提交的JIRA問題: [#SPR-8871] @Cachable condition should allow referencing return value - Spring Projects Issue Tracker

+0

嗨,我認爲你應該接受Tech Trip的回答,因爲它與當前版本的Spring更相關。 –

回答

59

萬歲,因爲Spring 3.2框架允許這種使用Spring SpeI和unless。從周圍可緩存的Java文檔註釋:

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

公共抽象的字符串,除非使用

春表達式語言(規劃環境地政司)屬性來否決方法緩存。

與條件()不同,該表達式在方法被調用後計算,因此可以引用結果。默認是「」,這意味着緩存永遠不會被否決。

重要的是在調用該方法後對unless進行評估。這非常合理,因爲如果密鑰已經在緩存中,該方法將永遠不會執行。

所以在上面的例子中,你會簡單地註釋如下(#result可用來測試方法的返回值):

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

我可以想象這個條件來自使用可插拔的緩存實現的如允許緩存空值的Ehcache。根據您的使用情況,這可能會也可能不需要。

+0

嗨,我有一個場景,其中redis緩存服務器緩存異常。我必須避免緩存服務器的例外情況。我可以使用「除非」參數嗎?有沒有可能在除非中提到例外?請分享你的建議。在此先感謝 – nijogeorgep

+0

JSR107提供了一種機制來始終調用註釋的方法,並仍然通過cacheResult#skipGet緩存結果。根據skipGet上的API,如果爲true,則也會跳過對引發的異常的預調用檢查。但是,如果在調用期間拋出異常,它將按照標準異常緩存規則進行緩存,因此可能不足以滿足您的需求。然而,使用JSR 107你可以明確地排除某些配置異常,也許這將允許你繼續進行。 (請參閱nonCachedExceptions) Spring的抽象提供了對JSR107註釋的支持。 – TechTrip

2

更新這個答案已經過時,現在,對Spring 3.2和更高版本請參閱Tech Trip的answer,OP:隨時將其標記爲已接受。

我不認爲這是可能的(即使是在春天的條件Cache驅逐可在方法調用後beforeInvocation組執行與@CacheEvict參數設置爲false,這是默認值)檢查CacheAspectSupport類顯示返回的值不存儲在調用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(); 
} 
0

如果春天註釋

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

不工作,你可以嘗試:

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

這對我的作品。

+5

你的意思是'unless =「#result == null」'? – cahen

+0

_Cache除非結果!= null_means _Cache如果結果== null_。所以,正確的表達式是'unless =「#result == null」'這意味着_Cache除非result == null_這意味着_Cache如果結果!= null_。 – mmdemirbas

相關問題