1
1
/*
2
- * Copyright 2002-2013 the original author or authors.
2
+ * Copyright 2002-2014 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
20
20
import java .util .ArrayList ;
21
21
import java .util .Collection ;
22
22
import java .util .Collections ;
23
+ import java .util .LinkedList ;
23
24
import java .util .List ;
24
25
import java .util .Set ;
25
26
29
30
import org .springframework .aop .framework .AopProxyUtils ;
30
31
import org .springframework .beans .factory .InitializingBean ;
31
32
import org .springframework .cache .Cache ;
32
- import org .springframework .cache .Cache .ValueWrapper ;
33
33
import org .springframework .cache .CacheManager ;
34
34
import org .springframework .cache .support .SimpleValueWrapper ;
35
35
import org .springframework .expression .EvaluationContext ;
64
64
* @author Chris Beams
65
65
* @author Phillip Webb
66
66
* @author Sam Brannen
67
+ * @author Stephane Nicoll
67
68
* @since 3.1
68
69
*/
69
70
public abstract class CacheAspectSupport implements InitializingBean {
@@ -194,15 +195,20 @@ private Object execute(Invoker invoker, CacheOperationContexts contexts) {
194
195
// Process any early evictions
195
196
processCacheEvicts (contexts .get (CacheEvictOperation .class ), true , ExpressionEvaluator .NO_RESULT );
196
197
197
- // Collect puts from any @Cachable miss
198
- List <CachePutRequest > cachePutRequests = new ArrayList <CachePutRequest >();
199
- collectPutRequests (contexts .get (CacheableOperation .class ), ExpressionEvaluator .NO_RESULT , cachePutRequests , true );
198
+ // Check if we have a cached item matching the conditions
199
+ Cache .ValueWrapper cacheHit = findCachedItem (contexts .get (CacheableOperation .class ));
200
200
201
- ValueWrapper result = null ;
201
+ // Collect puts from any @Cacheable miss, if no cached item is found
202
+ List <CachePutRequest > cachePutRequests = new LinkedList <CachePutRequest >();
203
+ if (cacheHit == null ) {
204
+ collectPutRequests (contexts .get (CacheableOperation .class ), ExpressionEvaluator .NO_RESULT , cachePutRequests );
205
+ }
206
+
207
+ Cache .ValueWrapper result = null ;
202
208
203
- // We only attempt to get a cached result if there are no put requests
209
+ // If there are no put requests, just use the cache hit
204
210
if (cachePutRequests .isEmpty () && contexts .get (CachePutOperation .class ).isEmpty ()) {
205
- result = findCachedResult ( contexts . get ( CacheableOperation . class )) ;
211
+ result = cacheHit ;
206
212
}
207
213
208
214
// Invoke the method if don't have a cache hit
@@ -211,7 +217,7 @@ private Object execute(Invoker invoker, CacheOperationContexts contexts) {
211
217
}
212
218
213
219
// Collect any explicit @CachePuts
214
- collectPutRequests (contexts .get (CachePutOperation .class ), result .get (), cachePutRequests , false );
220
+ collectPutRequests (contexts .get (CachePutOperation .class ), result .get (), cachePutRequests );
215
221
216
222
// Process any collected put requests, either from @CachePut or a @Cacheable miss
217
223
for (CachePutRequest cachePutRequest : cachePutRequests ) {
@@ -257,39 +263,42 @@ private void logInvalidating(CacheOperationContext context, CacheEvictOperation
257
263
}
258
264
}
259
265
260
- private void collectPutRequests (Collection <CacheOperationContext > contexts ,
261
- Object result , Collection <CachePutRequest > putRequests , boolean whenNotInCache ) {
262
-
266
+ /**
267
+ * Find a cached item only for {@link CacheableOperation} that passes the condition.
268
+ * @param contexts the cacheable operations
269
+ * @return a {@link Cache.ValueWrapper} holding the cached item,
270
+ * or {@code null} if none is found
271
+ */
272
+ private Cache .ValueWrapper findCachedItem (Collection <CacheOperationContext > contexts ) {
273
+ Object result = ExpressionEvaluator .NO_RESULT ;
263
274
for (CacheOperationContext context : contexts ) {
264
275
if (isConditionPassing (context , result )) {
265
276
Object key = generateKey (context , result );
266
- if (!whenNotInCache || findInAnyCaches (contexts , key ) == null ) {
267
- putRequests .add (new CachePutRequest (context , key ));
277
+ Cache .ValueWrapper cached = findInCaches (context , key );
278
+ if (cached != null ) {
279
+ return cached ;
268
280
}
269
281
}
270
282
}
283
+ return null ;
271
284
}
272
285
273
- private Cache .ValueWrapper findCachedResult (Collection <CacheOperationContext > contexts ) {
274
- ValueWrapper result = null ;
275
- for (CacheOperationContext context : contexts ) {
276
- if (isConditionPassing (context , ExpressionEvaluator .NO_RESULT )) {
277
- if (result == null ) {
278
- result = findInCaches (context , generateKey (context , ExpressionEvaluator .NO_RESULT ));
279
- }
280
- }
281
- }
282
- return result ;
283
- }
286
+ /**
287
+ * Collect the {@link CachePutRequest} for all {@link CacheOperation} using
288
+ * the specified result item.
289
+ * @param contexts the contexts to handle
290
+ * @param result the result item (never {@code null})
291
+ * @param putRequests the collection to update
292
+ */
293
+ private void collectPutRequests (Collection <CacheOperationContext > contexts ,
294
+ Object result , Collection <CachePutRequest > putRequests ) {
284
295
285
- private Cache .ValueWrapper findInAnyCaches (Collection <CacheOperationContext > contexts , Object key ) {
286
296
for (CacheOperationContext context : contexts ) {
287
- ValueWrapper wrapper = findInCaches ( context , key );
288
- if ( wrapper != null ) {
289
- return wrapper ;
297
+ if ( isConditionPassing ( context , result )) {
298
+ Object key = generateKey ( context , result );
299
+ putRequests . add ( new CachePutRequest ( context , key )) ;
290
300
}
291
301
}
292
- return null ;
293
302
}
294
303
295
304
private Cache .ValueWrapper findInCaches (CacheOperationContext context , Object key ) {
0 commit comments