Lazily retrieve delegate beans in AsyncConfigurer and CachingConfigurer

Introduces a configure method pattern for Supplier-style configuration and a common SingletonSupplier decorator for method reference suppliers. Also declares jcache.config and jcache.interceptor for non-null conventions.

Issue: SPR-17021
This commit is contained in:
Juergen Hoeller
2018-07-14 19:29:32 +02:00
parent 680afa75d8
commit f6fdffd663
53 changed files with 785 additions and 330 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
package org.springframework.cache.annotation;
import java.util.Collection;
import java.util.function.Supplier;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
@@ -36,6 +37,7 @@ import org.springframework.util.CollectionUtils;
*
* @author Chris Beams
* @author Stephane Nicoll
* @author Juergen Hoeller
* @since 3.1
* @see EnableCaching
*/
@@ -46,16 +48,16 @@ public abstract class AbstractCachingConfiguration implements ImportAware {
protected AnnotationAttributes enableCaching;
@Nullable
protected CacheManager cacheManager;
protected Supplier<CacheManager> cacheManager;
@Nullable
protected CacheResolver cacheResolver;
protected Supplier<CacheResolver> cacheResolver;
@Nullable
protected KeyGenerator keyGenerator;
protected Supplier<KeyGenerator> keyGenerator;
@Nullable
protected CacheErrorHandler errorHandler;
protected Supplier<CacheErrorHandler> errorHandler;
@Override
@@ -87,10 +89,10 @@ public abstract class AbstractCachingConfiguration implements ImportAware {
* Extract the configuration from the nominated {@link CachingConfigurer}.
*/
protected void useCachingConfigurer(CachingConfigurer config) {
this.cacheManager = config.cacheManager();
this.cacheResolver = config.cacheResolver();
this.keyGenerator = config.keyGenerator();
this.errorHandler = config.errorHandler();
this.cacheManager = config::cacheManager;
this.cacheResolver = config::cacheResolver;
this.keyGenerator = config::keyGenerator;
this.errorHandler = config::errorHandler;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -40,13 +40,13 @@ public class CachingConfigurerSupport implements CachingConfigurer {
@Override
@Nullable
public KeyGenerator keyGenerator() {
public CacheResolver cacheResolver() {
return null;
}
@Override
@Nullable
public CacheResolver cacheResolver() {
public KeyGenerator keyGenerator() {
return null;
}

View File

@@ -30,6 +30,7 @@ import org.springframework.context.annotation.Role;
* to enable proxy-based annotation-driven cache management.
*
* @author Chris Beams
* @author Juergen Hoeller
* @since 3.1
* @see EnableCaching
* @see CachingConfigurationSelector
@@ -61,19 +62,8 @@ public class ProxyCachingConfiguration extends AbstractCachingConfiguration {
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public CacheInterceptor cacheInterceptor() {
CacheInterceptor interceptor = new CacheInterceptor();
interceptor.setCacheOperationSources(cacheOperationSource());
if (this.cacheResolver != null) {
interceptor.setCacheResolver(this.cacheResolver);
}
else if (this.cacheManager != null) {
interceptor.setCacheManager(this.cacheManager);
}
if (this.keyGenerator != null) {
interceptor.setKeyGenerator(this.keyGenerator);
}
if (this.errorHandler != null) {
interceptor.setErrorHandler(this.errorHandler);
}
interceptor.configure(this.errorHandler, this.keyGenerator, this.cacheResolver, this.cacheManager);
interceptor.setCacheOperationSource(cacheOperationSource());
return interceptor;
}

View File

@@ -112,21 +112,21 @@ class AnnotationDrivenCacheBeanDefinitionParser implements BeanDefinitionParser
*/
private static void parseCacheResolution(Element element, BeanDefinition def, boolean setBoth) {
String name = element.getAttribute("cache-resolver");
if (StringUtils.hasText(name)) {
boolean hasText = StringUtils.hasText(name);
if (hasText) {
def.getPropertyValues().add("cacheResolver", new RuntimeBeanReference(name.trim()));
}
if (!StringUtils.hasText(name) || setBoth) {
if (!hasText || setBoth) {
def.getPropertyValues().add("cacheManager",
new RuntimeBeanReference(CacheNamespaceHandler.extractCacheManager(element)));
}
}
private static BeanDefinition parseErrorHandler(Element element, BeanDefinition def) {
private static void parseErrorHandler(Element element, BeanDefinition def) {
String name = element.getAttribute("error-handler");
if (StringUtils.hasText(name)) {
def.getPropertyValues().add("errorHandler", new RuntimeBeanReference(name.trim()));
}
return def;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,27 +18,28 @@ package org.springframework.cache.interceptor;
import org.springframework.cache.Cache;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.function.SingletonSupplier;
/**
* A base component for invoking {@link Cache} operations and using a
* configurable {@link CacheErrorHandler} when an exception occurs.
*
* @author Stephane Nicoll
* @author Juergen Hoeller
* @since 4.1
* @see org.springframework.cache.interceptor.CacheErrorHandler
*/
public abstract class AbstractCacheInvoker {
private CacheErrorHandler errorHandler;
protected SingletonSupplier<CacheErrorHandler> errorHandler;
protected AbstractCacheInvoker() {
this.errorHandler = new SimpleCacheErrorHandler();
this.errorHandler = SingletonSupplier.of(SimpleCacheErrorHandler::new);
}
protected AbstractCacheInvoker(CacheErrorHandler errorHandler) {
this.errorHandler = errorHandler;
this.errorHandler = SingletonSupplier.of(errorHandler);
}
@@ -48,15 +49,14 @@ public abstract class AbstractCacheInvoker {
* is used who throws any exception as is.
*/
public void setErrorHandler(CacheErrorHandler errorHandler) {
Assert.notNull(errorHandler, "CacheErrorHandler must not be null");
this.errorHandler = errorHandler;
this.errorHandler = SingletonSupplier.of(errorHandler);
}
/**
* Return the {@link CacheErrorHandler} to use.
*/
public CacheErrorHandler getErrorHandler() {
return this.errorHandler;
return this.errorHandler.obtain();
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -40,9 +40,17 @@ public abstract class AbstractCacheResolver implements CacheResolver, Initializi
private CacheManager cacheManager;
/**
* Construct a new {@code AbstractCacheResolver}.
* @see #setCacheManager
*/
protected AbstractCacheResolver() {
}
/**
* Construct a new {@code AbstractCacheResolver} for the given {@link CacheManager}.
* @param cacheManager the CacheManager to use
*/
protected AbstractCacheResolver(CacheManager cacheManager) {
this.cacheManager = cacheManager;
}

View File

@@ -26,6 +26,7 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -52,6 +53,8 @@ import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.util.function.SingletonSupplier;
import org.springframework.util.function.SupplierUtils;
/**
* Base class for caching aspects, such as the {@link CacheInterceptor} or an
@@ -89,10 +92,10 @@ public abstract class CacheAspectSupport extends AbstractCacheInvoker
@Nullable
private CacheOperationSource cacheOperationSource;
private KeyGenerator keyGenerator = new SimpleKeyGenerator();
private SingletonSupplier<KeyGenerator> keyGenerator = SingletonSupplier.of(SimpleKeyGenerator::new);
@Nullable
private CacheResolver cacheResolver;
private SingletonSupplier<CacheResolver> cacheResolver;
@Nullable
private BeanFactory beanFactory;
@@ -100,10 +103,27 @@ public abstract class CacheAspectSupport extends AbstractCacheInvoker
private boolean initialized = false;
/**
* Configure this aspect with the given error handler, key generator and cache resolver/manager
* suppliers, applying the corresponding default if a supplier is not resolvable.
* @since 5.1
*/
public void configure(
@Nullable Supplier<CacheErrorHandler> errorHandler, @Nullable Supplier<KeyGenerator> keyGenerator,
@Nullable Supplier<CacheResolver> cacheResolver, @Nullable Supplier<CacheManager> cacheManager) {
this.errorHandler = new SingletonSupplier<>(errorHandler, SimpleCacheErrorHandler::new);
this.keyGenerator = new SingletonSupplier<>(keyGenerator, SimpleKeyGenerator::new);
this.cacheResolver = new SingletonSupplier<>(cacheResolver,
() -> SimpleCacheResolver.of(SupplierUtils.resolve(cacheManager)));
}
/**
* Set one or more cache operation sources which are used to find the cache
* attributes. If more than one source is provided, they will be aggregated
* using a {@link CompositeCacheOperationSource}.
* @see #setCacheOperationSource
*/
public void setCacheOperationSources(CacheOperationSource... cacheOperationSources) {
Assert.notEmpty(cacheOperationSources, "At least 1 CacheOperationSource needs to be specified");
@@ -111,6 +131,15 @@ public abstract class CacheAspectSupport extends AbstractCacheInvoker
new CompositeCacheOperationSource(cacheOperationSources) : cacheOperationSources[0]);
}
/**
* Set the CacheOperationSource for this cache aspect.
* @since 5.1
* @see #setCacheOperationSources
*/
public void setCacheOperationSource(@Nullable CacheOperationSource cacheOperationSource) {
this.cacheOperationSource = cacheOperationSource;
}
/**
* Return the CacheOperationSource for this cache aspect.
*/
@@ -125,14 +154,14 @@ public abstract class CacheAspectSupport extends AbstractCacheInvoker
* <p>The default is a {@link SimpleKeyGenerator}.
*/
public void setKeyGenerator(KeyGenerator keyGenerator) {
this.keyGenerator = keyGenerator;
this.keyGenerator = SingletonSupplier.of(keyGenerator);
}
/**
* Return the default {@link KeyGenerator} that this cache aspect delegates to.
*/
public KeyGenerator getKeyGenerator() {
return this.keyGenerator;
return this.keyGenerator.obtain();
}
/**
@@ -144,7 +173,7 @@ public abstract class CacheAspectSupport extends AbstractCacheInvoker
* @see SimpleCacheResolver
*/
public void setCacheResolver(@Nullable CacheResolver cacheResolver) {
this.cacheResolver = cacheResolver;
this.cacheResolver = SingletonSupplier.ofNullable(cacheResolver);
}
/**
@@ -152,7 +181,7 @@ public abstract class CacheAspectSupport extends AbstractCacheInvoker
*/
@Nullable
public CacheResolver getCacheResolver() {
return this.cacheResolver;
return SupplierUtils.resolve(this.cacheResolver);
}
/**
@@ -162,7 +191,7 @@ public abstract class CacheAspectSupport extends AbstractCacheInvoker
* @see SimpleCacheResolver
*/
public void setCacheManager(CacheManager cacheManager) {
this.cacheResolver = new SimpleCacheResolver(cacheManager);
this.cacheResolver = SingletonSupplier.of(new SimpleCacheResolver(cacheManager));
}
/**
@@ -192,8 +221,7 @@ public abstract class CacheAspectSupport extends AbstractCacheInvoker
}
catch (NoUniqueBeanDefinitionException ex) {
throw new IllegalStateException("No CacheResolver specified, and no unique bean of type " +
"CacheManager found. Mark one as primary (or give it the name 'cacheManager') or " +
"declare a specific CacheManager to use, that serves as the default one.");
"CacheManager found. Mark one as primary or declare a specific CacheManager to use.");
}
catch (NoSuchBeanDefinitionException ex) {
throw new IllegalStateException("No CacheResolver specified, and no bean of type CacheManager found. " +

View File

@@ -20,6 +20,7 @@ import java.util.Collection;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.lang.Nullable;
/**
* A simple {@link CacheResolver} that resolves the {@link Cache} instance(s)
@@ -27,14 +28,23 @@ import org.springframework.cache.CacheManager;
* cache(s) as provided by {@link BasicOperation#getCacheNames() getCacheNames()}.
*
* @author Stephane Nicoll
* @author Juergen Hoeller
* @since 4.1
* @see BasicOperation#getCacheNames()
*/
public class SimpleCacheResolver extends AbstractCacheResolver {
/**
* Construct a new {@code SimpleCacheResolver}.
* @see #setCacheManager
*/
public SimpleCacheResolver() {
}
/**
* Construct a new {@code SimpleCacheResolver} for the given {@link CacheManager}.
* @param cacheManager the CacheManager to use
*/
public SimpleCacheResolver(CacheManager cacheManager) {
super(cacheManager);
}
@@ -45,4 +55,16 @@ public class SimpleCacheResolver extends AbstractCacheResolver {
return context.getOperation().getCacheNames();
}
/**
* Return a {@code SimpleCacheResolver} for the given {@link CacheManager}.
* @param cacheManager the CacheManager (potentially {@code null})
* @return the SimpleCacheResolver ({@code null} if the CacheManager was {@code null})
* @since 5.1
*/
@Nullable
static SimpleCacheResolver of(@Nullable CacheManager cacheManager) {
return (cacheManager != null ? new SimpleCacheResolver(cacheManager) : null);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@ package org.springframework.scheduling.annotation;
import java.util.Collection;
import java.util.concurrent.Executor;
import java.util.function.Supplier;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.beans.factory.annotation.Autowired;
@@ -33,6 +34,7 @@ import org.springframework.util.CollectionUtils;
* Spring's asynchronous method execution capability.
*
* @author Chris Beams
* @author Juergen Hoeller
* @author Stephane Nicoll
* @since 3.1
* @see EnableAsync
@@ -44,10 +46,10 @@ public abstract class AbstractAsyncConfiguration implements ImportAware {
protected AnnotationAttributes enableAsync;
@Nullable
protected Executor executor;
protected Supplier<Executor> executor;
@Nullable
protected AsyncUncaughtExceptionHandler exceptionHandler;
protected Supplier<AsyncUncaughtExceptionHandler> exceptionHandler;
@Override
@@ -72,8 +74,8 @@ public abstract class AbstractAsyncConfiguration implements ImportAware {
throw new IllegalStateException("Only one AsyncConfigurer may exist");
}
AsyncConfigurer configurer = configurers.iterator().next();
this.executor = configurer.getAsyncExecutor();
this.exceptionHandler = configurer.getAsyncUncaughtExceptionHandler();
this.executor = configurer::getAsyncExecutor;
this.exceptionHandler = configurer::getAsyncUncaughtExceptionHandler;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,12 +21,12 @@ import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.function.Supplier;
import org.aopalliance.aop.Advice;
import org.springframework.aop.Pointcut;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler;
import org.springframework.aop.support.AbstractPointcutAdvisor;
import org.springframework.aop.support.ComposablePointcut;
import org.springframework.aop.support.annotation.AnnotationMatchingPointcut;
@@ -35,6 +35,7 @@ import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.function.SingletonSupplier;
/**
* Advisor that activates asynchronous method execution through the {@link Async}
@@ -54,8 +55,6 @@ import org.springframework.util.ClassUtils;
@SuppressWarnings("serial")
public class AsyncAnnotationAdvisor extends AbstractPointcutAdvisor implements BeanFactoryAware {
private AsyncUncaughtExceptionHandler exceptionHandler;
private Advice advice;
private Pointcut pointcut;
@@ -65,7 +64,7 @@ public class AsyncAnnotationAdvisor extends AbstractPointcutAdvisor implements B
* Create a new {@code AsyncAnnotationAdvisor} for bean-style configuration.
*/
public AsyncAnnotationAdvisor() {
this(null, null);
this((Supplier<Executor>) null, (Supplier<AsyncUncaughtExceptionHandler>) null);
}
/**
@@ -77,7 +76,25 @@ public class AsyncAnnotationAdvisor extends AbstractPointcutAdvisor implements B
* @see AnnotationAsyncExecutionInterceptor#getDefaultExecutor(BeanFactory)
*/
@SuppressWarnings("unchecked")
public AsyncAnnotationAdvisor(@Nullable Executor executor, @Nullable AsyncUncaughtExceptionHandler exceptionHandler) {
public AsyncAnnotationAdvisor(
@Nullable Executor executor, @Nullable AsyncUncaughtExceptionHandler exceptionHandler) {
this(SingletonSupplier.ofNullable(executor), SingletonSupplier.ofNullable(exceptionHandler));
}
/**
* Create a new {@code AsyncAnnotationAdvisor} for the given task executor.
* @param executor the task executor to use for asynchronous methods
* (can be {@code null} to trigger default executor resolution)
* @param exceptionHandler the {@link AsyncUncaughtExceptionHandler} to use to
* handle unexpected exception thrown by asynchronous method executions
* @since 5.1
* @see AnnotationAsyncExecutionInterceptor#getDefaultExecutor(BeanFactory)
*/
@SuppressWarnings("unchecked")
public AsyncAnnotationAdvisor(
@Nullable Supplier<Executor> executor, @Nullable Supplier<AsyncUncaughtExceptionHandler> exceptionHandler) {
Set<Class<? extends Annotation>> asyncAnnotationTypes = new LinkedHashSet<>(2);
asyncAnnotationTypes.add(Async.class);
try {
@@ -87,24 +104,11 @@ public class AsyncAnnotationAdvisor extends AbstractPointcutAdvisor implements B
catch (ClassNotFoundException ex) {
// If EJB 3.1 API not present, simply ignore.
}
if (exceptionHandler != null) {
this.exceptionHandler = exceptionHandler;
}
else {
this.exceptionHandler = new SimpleAsyncUncaughtExceptionHandler();
}
this.advice = buildAdvice(executor, this.exceptionHandler);
this.advice = buildAdvice(executor, exceptionHandler);
this.pointcut = buildPointcut(asyncAnnotationTypes);
}
/**
* Specify the default task executor to use for asynchronous methods.
*/
public void setTaskExecutor(Executor executor) {
this.advice = buildAdvice(executor, this.exceptionHandler);
}
/**
* Set the 'async' annotation type.
* <p>The default async annotation type is the {@link Async} annotation, as well
@@ -143,8 +147,12 @@ public class AsyncAnnotationAdvisor extends AbstractPointcutAdvisor implements B
}
protected Advice buildAdvice(@Nullable Executor executor, AsyncUncaughtExceptionHandler exceptionHandler) {
return new AnnotationAsyncExecutionInterceptor(executor, exceptionHandler);
protected Advice buildAdvice(
@Nullable Supplier<Executor> executor, @Nullable Supplier<AsyncUncaughtExceptionHandler> exceptionHandler) {
AnnotationAsyncExecutionInterceptor interceptor = new AnnotationAsyncExecutionInterceptor(null);
interceptor.configure(executor, exceptionHandler);
return interceptor;
}
/**

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@ package org.springframework.scheduling.annotation;
import java.lang.annotation.Annotation;
import java.util.concurrent.Executor;
import java.util.function.Supplier;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -28,6 +29,7 @@ import org.springframework.beans.factory.BeanFactory;
import org.springframework.core.task.TaskExecutor;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.function.SingletonSupplier;
/**
* Bean post-processor that automatically applies asynchronous invocation
@@ -75,14 +77,15 @@ public class AsyncAnnotationBeanPostProcessor extends AbstractBeanFactoryAwareAd
protected final Log logger = LogFactory.getLog(getClass());
@Nullable
private Supplier<Executor> executor;
@Nullable
private Supplier<AsyncUncaughtExceptionHandler> exceptionHandler;
@Nullable
private Class<? extends Annotation> asyncAnnotationType;
@Nullable
private Executor executor;
@Nullable
private AsyncUncaughtExceptionHandler exceptionHandler;
public AsyncAnnotationBeanPostProcessor() {
@@ -90,6 +93,40 @@ public class AsyncAnnotationBeanPostProcessor extends AbstractBeanFactoryAwareAd
}
/**
* Configure this post-processor with the given executor and exception handler suppliers,
* applying the corresponding default if a supplier is not resolvable.
* @since 5.1
*/
public void configure(
@Nullable Supplier<Executor> executor, @Nullable Supplier<AsyncUncaughtExceptionHandler> exceptionHandler) {
this.executor = executor;
this.exceptionHandler = exceptionHandler;
}
/**
* Set the {@link Executor} to use when invoking methods asynchronously.
* <p>If not specified, default executor resolution will apply: searching for a
* unique {@link TaskExecutor} bean in the context, or for an {@link Executor}
* bean named "taskExecutor" otherwise. If neither of the two is resolvable,
* a local default executor will be created within the interceptor.
* @see AnnotationAsyncExecutionInterceptor#getDefaultExecutor(BeanFactory)
* @see #DEFAULT_TASK_EXECUTOR_BEAN_NAME
*/
public void setExecutor(Executor executor) {
this.executor = SingletonSupplier.of(executor);
}
/**
* Set the {@link AsyncUncaughtExceptionHandler} to use to handle uncaught
* exceptions thrown by asynchronous method executions.
* @since 4.1
*/
public void setExceptionHandler(AsyncUncaughtExceptionHandler exceptionHandler) {
this.exceptionHandler = SingletonSupplier.of(exceptionHandler);
}
/**
* Set the 'async' annotation type to be detected at either class or method
* level. By default, both the {@link Async} annotation and the EJB 3.1
@@ -104,29 +141,6 @@ public class AsyncAnnotationBeanPostProcessor extends AbstractBeanFactoryAwareAd
this.asyncAnnotationType = asyncAnnotationType;
}
/**
* Set the {@link Executor} to use when invoking methods asynchronously.
* <p>If not specified, default executor resolution will apply: searching for a
* unique {@link TaskExecutor} bean in the context, or for an {@link Executor}
* bean named "taskExecutor" otherwise. If neither of the two is resolvable,
* a local default executor will be created within the interceptor.
* @see AsyncAnnotationAdvisor#AsyncAnnotationAdvisor(Executor, AsyncUncaughtExceptionHandler)
* @see AnnotationAsyncExecutionInterceptor#getDefaultExecutor(BeanFactory)
* @see #DEFAULT_TASK_EXECUTOR_BEAN_NAME
*/
public void setExecutor(Executor executor) {
this.executor = executor;
}
/**
* Set the {@link AsyncUncaughtExceptionHandler} to use to handle uncaught
* exceptions thrown by asynchronous method executions.
* @since 4.1
*/
public void setExceptionHandler(AsyncUncaughtExceptionHandler exceptionHandler) {
this.exceptionHandler = exceptionHandler;
}
@Override
public void setBeanFactory(BeanFactory beanFactory) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,6 +32,7 @@ import org.springframework.util.Assert;
*
* @author Chris Beams
* @author Stephane Nicoll
* @author Juergen Hoeller
* @since 3.1
* @see EnableAsync
* @see AsyncConfigurationSelector
@@ -45,16 +46,11 @@ public class ProxyAsyncConfiguration extends AbstractAsyncConfiguration {
public AsyncAnnotationBeanPostProcessor asyncAdvisor() {
Assert.notNull(this.enableAsync, "@EnableAsync annotation metadata was not injected");
AsyncAnnotationBeanPostProcessor bpp = new AsyncAnnotationBeanPostProcessor();
bpp.configure(this.executor, this.exceptionHandler);
Class<? extends Annotation> customAsyncAnnotation = this.enableAsync.getClass("annotation");
if (customAsyncAnnotation != AnnotationUtils.getDefaultValue(EnableAsync.class, "annotation")) {
bpp.setAsyncAnnotationType(customAsyncAnnotation);
}
if (this.executor != null) {
bpp.setExecutor(this.executor);
}
if (this.exceptionHandler != null) {
bpp.setExceptionHandler(this.exceptionHandler);
}
bpp.setProxyTargetClass(this.enableAsync.getBoolean("proxyTargetClass"));
bpp.setOrder(this.enableAsync.<Integer>getNumber("order"));
return bpp;