Fix mutually exclusive use of CachePut and Cacheable

Commit eea230f introduced a regression by adding a support for the
"result" variable in SpEL expression for @CachePut. As such expressions
cannot be evaluated upfront anymore, any method that contains both
@Cacheable and @CachePut annotations are always executed even when
their conditions are mutually exclusive.

This is an example of such mutual exclusion

@Cacheable(condition = "#p1", key = "#p0")
@CachePut(condition = "!#p1", key = "#p0")
public Object getFooById(Object id, boolean flag) { ... }

This commit updates CacheEvaluationContext to define a set of
unavailable variables. When such variable is accessed for a given
expression, an exception is thrown. This is used to restore the
evaluation of the @CachePut condition upfront by registering "result"
as an unavailable variable.

If all @CachePut operations have been excluded by this upfront check,
the @Cacheable operation is processed as it was before. Such upfront
check restore the behavior prior to eea230f.

Issue: SPR-11955
This commit is contained in:
Stephane Nicoll
2014-07-05 11:26:05 +02:00
parent a8848cb670
commit e20ac27fb4
7 changed files with 274 additions and 16 deletions

View File

@@ -47173,11 +47173,13 @@ than method flow optimization:
[IMPORTANT]
====
Note that using `@CachePut` and `@Cacheable` annotations on the same method is generally
discouraged because they have different behaviors. While the latter causes the method
execution to be skipped by using the cache, the former forces the execution in order to
execute a cache update. This leads to unexpected behavior and with the exception of
strongly discouraged because they have different behaviors. While the latter causes the
method execution to be skipped by using the cache, the former forces the execution in
order to execute a cache update. This leads to unexpected behavior and with the exception of
specific corner-cases (such as annotations having conditions that exclude them from each
other), such declarations should be avoided.
other), such declarations should be avoided. Note also that such conditions should not rely
on the result object (i.e. the `#result` variable) as these are validated upfront to confirm
the exclusion.
====