All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springframework.scheduling.annotation.AsyncAnnotationBeanPostProcessor Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2002-2015 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.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.scheduling.annotation;

import java.lang.annotation.Annotation;
import java.util.concurrent.Executor;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.aop.framework.AbstractAdvisingBeanPostProcessor;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
import org.springframework.core.task.TaskExecutor;
import org.springframework.util.Assert;

/**
 * Bean post-processor that automatically applies asynchronous invocation
 * behavior to any bean that carries the {@link Async} annotation at class or
 * method-level by adding a corresponding {@link AsyncAnnotationAdvisor} to the
 * exposed proxy (either an existing AOP proxy or a newly generated proxy that
 * implements all of the target's interfaces).
 *
 * 

The {@link TaskExecutor} responsible for the asynchronous execution may * be provided as well as the annotation type that indicates a method should be * invoked asynchronously. If no annotation type is specified, this post- * processor will detect both Spring's {@link Async @Async} annotation as well * as the EJB 3.1 {@code javax.ejb.Asynchronous} annotation. * *

For methods having a {@code void} return type, any exception thrown * during the asynchronous method invocation cannot be accessed by the * caller. An {@link AsyncUncaughtExceptionHandler} can be specified to handle * these cases. * *

Note: The underlying async advisor applies before existing advisors by default, * in order to switch to async execution as early as possible in the invocation chain. * * @author Mark Fisher * @author Juergen Hoeller * @author Stephane Nicoll * @since 3.0 * @see Async * @see AsyncAnnotationAdvisor * @see #setBeforeExistingAdvisors * @see ScheduledAnnotationBeanPostProcessor */ @SuppressWarnings("serial") public class AsyncAnnotationBeanPostProcessor extends AbstractAdvisingBeanPostProcessor implements BeanFactoryAware { /** * The default name of the {@link TaskExecutor} bean to pick up: "taskExecutor". *

Note that the initial lookup happens by type; this is just the fallback * in case of multiple executor beans found in the context. */ public static final String DEFAULT_TASK_EXECUTOR_BEAN_NAME = "taskExecutor"; protected final Log logger = LogFactory.getLog(getClass()); private Class asyncAnnotationType; private Executor executor; private AsyncUncaughtExceptionHandler exceptionHandler; public AsyncAnnotationBeanPostProcessor() { setBeforeExistingAdvisors(true); } /** * 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 * {@code javax.ejb.Asynchronous} annotation will be detected. *

This setter property exists so that developers can provide their own * (non-Spring-specific) annotation type to indicate that a method (or all * methods of a given class) should be invoked asynchronously. * @param asyncAnnotationType the desired annotation type */ public void setAsyncAnnotationType(Class asyncAnnotationType) { Assert.notNull(asyncAnnotationType, "'asyncAnnotationType' must not be null"); this.asyncAnnotationType = asyncAnnotationType; } /** * Set the {@link Executor} to use when invoking methods asynchronously. */ 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) { Executor executorToUse = this.executor; if (executorToUse == null) { try { // Search for TaskExecutor bean... not plain Executor since that would // match with ScheduledExecutorService as well, which is unusable for // our purposes here. TaskExecutor is more clearly designed for it. executorToUse = beanFactory.getBean(TaskExecutor.class); } catch (NoUniqueBeanDefinitionException ex) { try { executorToUse = beanFactory.getBean(DEFAULT_TASK_EXECUTOR_BEAN_NAME, TaskExecutor.class); } catch (NoSuchBeanDefinitionException ex2) { throw new IllegalStateException("More than one TaskExecutor bean exists within the context, " + "and none is named 'taskExecutor'. Mark one of them as primary or name it " + "'taskExecutor' (possibly as an alias); or specify the AsyncConfigurer interface " + "and implement getAsyncExecutor() accordingly.", ex); } } catch (NoSuchBeanDefinitionException ex) { logger.debug("Could not find default TaskExecutor bean", ex); // Giving up -> falling back to default executor within the advisor... } } AsyncAnnotationAdvisor advisor = new AsyncAnnotationAdvisor(executorToUse, this.exceptionHandler); if (this.asyncAnnotationType != null) { advisor.setAsyncAnnotationType(this.asyncAnnotationType); } advisor.setBeanFactory(beanFactory); this.advisor = advisor; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy