Lazily resolve the default exception CacheResolver

This is a rework of 314b069 that may still lead to issue if a Cacheable
annotated bean is inspected on startup. Instead of resolving the default
exception CacheResolver if a cache operation is parsed, we resolve it as
late as possible (i.e. when an exception is thrown and the relevant
exception cache needs to be resolved)

Issue: SPR-12850
This commit is contained in:
Stephane Nicoll 2015-03-27 09:42:06 +01:00
parent 867971de89
commit a7fec6a459
2 changed files with 31 additions and 2 deletions

View File

@ -16,6 +16,8 @@
package org.springframework.cache.jcache.interceptor;
import java.util.Collection;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
@ -23,7 +25,9 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.interceptor.CacheOperationInvocationContext;
import org.springframework.cache.interceptor.CacheResolver;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.cache.interceptor.SimpleCacheResolver;
@ -179,7 +183,7 @@ public class DefaultJCacheOperationSource extends AnnotationJCacheOperationSourc
@Override
protected CacheResolver getDefaultExceptionCacheResolver() {
if (this.exceptionCacheResolver == null) {
this.exceptionCacheResolver = new SimpleExceptionCacheResolver(getDefaultCacheManager());
this.exceptionCacheResolver = new LazyCacheResolver();
}
return this.exceptionCacheResolver;
}
@ -189,4 +193,29 @@ public class DefaultJCacheOperationSource extends AnnotationJCacheOperationSourc
return this.adaptedKeyGenerator;
}
/**
* Only resolve the default exception cache resolver when an exception needs to be handled.
* <p>
* A non-JSR-107 setup requires either a {@link CacheManager} or a {@link CacheResolver}. If only
* the latter is specified, it is not possible to extract a default exception {@code CacheResolver}
* from a custom {@code CacheResolver} implementation so we have to fallback on the {@code CacheManager}.
* <p>
* This gives this weird situation of a perfectly valid configuration that breaks all the sudden
* because the JCache support is enabled. To avoid this we resolve the default exception {@code CacheResolver}
* as late as possible to avoid such hard requirement in other cases.
*/
class LazyCacheResolver implements CacheResolver {
private CacheResolver cacheResolver;
@Override
public Collection<? extends Cache> resolveCaches(CacheOperationInvocationContext<?> context) {
if (this.cacheResolver == null) {
this.cacheResolver = new SimpleExceptionCacheResolver(getDefaultCacheManager());
}
return this.cacheResolver.resolveCaches(context);
}
}
}

View File

@ -102,7 +102,7 @@ public class JCacheJavaConfigTests extends AbstractJCacheAnnotationTests {
}
@Test
public void exceptionCacheResolverFallbacksToMainOne() {
public void exceptionCacheResolverLazilyRequired() {
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(
NoExceptionCacheResolverConfig.class);
try {