2012-08-24 6 views
35

Gibt es eine Möglichkeit anzugeben, dass das Ergebnis in @Cacheable-Annotation für eine Methode wie dieses nicht zwischengespeichert wird, wenn die Methode null zurückgibt?Wie kann ich Spring-Cache mitteilen, dass in @Cacheable-Annotation kein Nullwert zwischengespeichert werden soll

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

Update: hier ist die vorgelegte JIRA Frage in Bezug auf Caching-Nullwert im November letztes Jahr, die noch nicht gelöst hat: [#SPR-8871] @Cachable condition should allow referencing return value - Spring Projects Issue Tracker

+0

Hallo, ich denke du solltest die Antwort von Tech Trip als akzeptiert akzeptieren, weil es relevanter für die aktuelle Version von Spring ist. –

Antwort

59

Hurra, ab Frühling 3.2 den Rahmen ermöglicht diese mit Spring SPEL und unless. Hinweis aus der Java-doc Umgebung Cacheable:

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

public abstract String, es sei denn

Frühling Expression Language (Spel) Attribut verwendet, um Verfahren Caching Veto einzulegen.

Im Gegensatz zu condition() wird dieser Ausdruck nach dem Aufruf der Methode ausgewertet und kann sich daher auf das Ergebnis beziehen. Der Standardwert ist "", was bedeutet, dass das Caching nie abgelehnt wird.

Der wichtige Aspekt ist, dass unless ausgewertet wird, nachdem die Methode aufgerufen wurde. Dies ist sehr sinnvoll, da die Methode niemals ausgeführt wird, wenn sich der Schlüssel bereits im Cache befindet.

So im obigen Beispiel würden Sie einfach mit Anmerkungen versehen wie folgt (#result verfügbar, um den Rückgabewert einer Methode zu testen):

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

Ich könnte mir vorstellen, diese Bedingung ergibt sich aus der Verwendung von steckbaren Cache-Implementierungen wie Ehcache, der das Zwischenspeichern von Nullen ermöglicht. Abhängig von Ihrem Anwendungsfall kann dies wünschenswert sein oder auch nicht.

+0

Hallo, ich habe ein Szenario, in dem Redis Caching-Server Ausnahmen zwischenspeichert. Ich muss verhindern, dass Ausnahmen vom Server zwischengespeichert werden. Kann ich "unless" -Parameter dafür verwenden? Ist es möglich, Ausnahmen zu erwähnen, außer? Bitte teilen Sie Ihre Vorschläge mit.Vielen Dank im Voraus – nijogeorgep

+0

JSR107 bietet einen Mechanismus, um immer die annotierte Methode aufzurufen und das Ergebnis trotzdem über cacheResult # skipGet zwischenzuspeichern. Entsprechend der API für skipGet, wenn "true", wird auch die Überprüfung vor dem Aufruf einer ausgelösten Ausnahme übersprungen. Wenn jedoch während des Aufrufs eine Ausnahme ausgelöst wird, wird sie nach den standardmäßigen Caching-Regeln für Ausnahmen zwischengespeichert, sodass sie für Ihre Anforderungen möglicherweise nicht ausreichen. Mit JSR 107 können Sie bestimmte Ausnahmen bei der Konfiguration explizit ausschließen, und vielleicht können Sie damit weitermachen. (siehe nonCachedExceptions) Die Abstraktion von Spring bietet Unterstützung für JSR107-Annotationen. – TechTrip

2

Update diese Antwort jetzt veraltet ist, für den Frühling 3.2 und später siehe Tech Trips answer, OP: Fühlen Sie sich frei, es als akzeptiert zu markieren.

Ich glaube nicht, dass es möglich ist (obwohl es bedingt Cache Räumung im Frühjahr, die beforeInvocation Satz falsch mit @CacheEvict Parametern nach dem Methodenaufruf ausgeführt werden kann, der Standardwert ist) prüft die CacheAspectSupport Klasse zeigt, dass Der zurückgegebene Wert wird nicht vor dem Aufruf inspectAfterCacheEvicts(ops.get(EVICT)); gespeichert.

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

Wenn Frühling Anmerkung

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

nicht funktioniert, können Sie versuchen:

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

Es funktioniert für mich.

+5

meinst du "es sei denn =" # result == null "'? – cahen

+0

_Cache, außer Ergebnis! = Null_Mewerte _Cache if result == null_. Der korrekte Ausdruck ist also 'ifing = "# result == null" 'was bedeutet: _Cache, es sei denn result == null_ was bedeutet: _Cache if result! = Null_. – mmdemirbas

Verwandte Themen