@ -40,7 +40,6 @@ import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils ;
import org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils ;
import org.springframework.cache.Cache ;
import org.springframework.cache.Cache ;
import org.springframework.cache.CacheManager ;
import org.springframework.cache.CacheManager ;
import org.springframework.context.ApplicationContext ;
import org.springframework.context.expression.AnnotatedElementKey ;
import org.springframework.context.expression.AnnotatedElementKey ;
import org.springframework.expression.EvaluationContext ;
import org.springframework.expression.EvaluationContext ;
import org.springframework.lang.UsesJava8 ;
import org.springframework.lang.UsesJava8 ;
@ -361,12 +360,12 @@ public abstract class CacheAspectSupport extends AbstractCacheInvoker
Object key = generateKey ( context , CacheOperationExpressionEvaluator . NO_RESULT ) ;
Object key = generateKey ( context , CacheOperationExpressionEvaluator . NO_RESULT ) ;
Cache cache = context . getCaches ( ) . iterator ( ) . next ( ) ;
Cache cache = context . getCaches ( ) . iterator ( ) . next ( ) ;
try {
try {
return cache . get ( key , new Callable < Object > ( ) {
return wrapCacheValue ( method , cache . get ( key , new Callable < Object > ( ) {
@Override
@Override
public Object call ( ) throws Exception {
public Object call ( ) throws Exception {
return invokeOperation ( invoker ) ;
return unwrapReturnValue ( invokeOperation ( invoker ) ) ;
}
}
} ) ;
} ) ) ;
}
}
catch ( Cache . ValueRetrievalException ex ) {
catch ( Cache . ValueRetrievalException ex ) {
// The invoker wraps any Throwable in a ThrowableWrapper instance so we
// The invoker wraps any Throwable in a ThrowableWrapper instance so we
@ -401,23 +400,12 @@ public abstract class CacheAspectSupport extends AbstractCacheInvoker
if ( cacheHit ! = null & & cachePutRequests . isEmpty ( ) & & ! hasCachePut ( contexts ) ) {
if ( cacheHit ! = null & & cachePutRequests . isEmpty ( ) & & ! hasCachePut ( contexts ) ) {
// If there are no put requests, just use the cache hit
// If there are no put requests, just use the cache hit
cacheValue = cacheHit . get ( ) ;
cacheValue = cacheHit . get ( ) ;
if ( method . getReturnType ( ) = = javaUtilOptionalClass & &
returnValue = wrapCacheValue ( method , cacheValue ) ;
( cacheValue = = null | | cacheValue . getClass ( ) ! = javaUtilOptionalClass ) ) {
returnValue = OptionalUnwrapper . wrap ( cacheValue ) ;
}
else {
returnValue = cacheValue ;
}
}
}
else {
else {
// Invoke the method if we don't have a cache hit
// Invoke the method if we don't have a cache hit
returnValue = invokeOperation ( invoker ) ;
returnValue = invokeOperation ( invoker ) ;
if ( returnValue ! = null & & returnValue . getClass ( ) = = javaUtilOptionalClass ) {
cacheValue = unwrapReturnValue ( returnValue ) ;
cacheValue = OptionalUnwrapper . unwrap ( returnValue ) ;
}
else {
cacheValue = returnValue ;
}
}
}
// Collect any explicit @CachePuts
// Collect any explicit @CachePuts
@ -434,6 +422,21 @@ public abstract class CacheAspectSupport extends AbstractCacheInvoker
return returnValue ;
return returnValue ;
}
}
private Object wrapCacheValue ( Method method , Object cacheValue ) {
if ( method . getReturnType ( ) = = Optional . class & &
( cacheValue = = null | | cacheValue . getClass ( ) ! = Optional . class ) ) {
return Optional . ofNullable ( cacheValue ) ;
}
return cacheValue ;
}
private Object unwrapReturnValue ( Object returnValue ) {
if ( returnValue ! = null & & returnValue . getClass ( ) = = javaUtilOptionalClass ) {
return OptionalUnwrapper . unwrap ( returnValue ) ;
}
return returnValue ;
}
private boolean hasCachePut ( CacheOperationContexts contexts ) {
private boolean hasCachePut ( CacheOperationContexts contexts ) {
// Evaluate the conditions *without* the result object because we don't have it yet...
// Evaluate the conditions *without* the result object because we don't have it yet...
Collection < CacheOperationContext > cachePutContexts = contexts . get ( CachePutOperation . class ) ;
Collection < CacheOperationContext > cachePutContexts = contexts . get ( CachePutOperation . class ) ;