1 /* 2 * Copyright 2002-2014 the original author or authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package org.springframework.scheduling.annotation; 18 19 import java.lang.annotation.Annotation; 20 import java.util.concurrent.Executor; 21 22 import org.springframework.aop.framework.AbstractAdvisingBeanPostProcessor; 23 import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; 24 import org.springframework.beans.factory.BeanFactory; 25 import org.springframework.beans.factory.BeanFactoryAware; 26 import org.springframework.core.task.TaskExecutor; 27 import org.springframework.util.Assert; 28 29 /** 30 * Bean post-processor that automatically applies asynchronous invocation 31 * behavior to any bean that carries the {@link Async} annotation at class or 32 * method-level by adding a corresponding {@link AsyncAnnotationAdvisor} to the 33 * exposed proxy (either an existing AOP proxy or a newly generated proxy that 34 * implements all of the target's interfaces). 35 * 36 * <p>The {@link TaskExecutor} responsible for the asynchronous execution may 37 * be provided as well as the annotation type that indicates a method should be 38 * invoked asynchronously. If no annotation type is specified, this post- 39 * processor will detect both Spring's {@link Async @Async} annotation as well 40 * as the EJB 3.1 {@code javax.ejb.Asynchronous} annotation. 41 * 42 * <p>For methods having a {@code void} return type, any exception thrown 43 * during the asynchronous method invocation cannot be accessed by the 44 * caller. An {@link AsyncUncaughtExceptionHandler} can be specified to handle 45 * these cases. 46 * 47 * <p>Note: The underlying async advisor applies before existing advisors by default, 48 * in order to switch to async execution as early as possible in the invocation chain. 49 * 50 * @author Mark Fisher 51 * @author Juergen Hoeller 52 * @author Stephane Nicoll 53 * @since 3.0 54 * @see Async 55 * @see AsyncAnnotationAdvisor 56 * @see #setBeforeExistingAdvisors 57 */ 58 @SuppressWarnings("serial") 59 public class AsyncAnnotationBeanPostProcessor extends AbstractAdvisingBeanPostProcessor implements BeanFactoryAware { 60 61 private Class<? extends Annotation> asyncAnnotationType; 62 63 private Executor executor; 64 65 private AsyncUncaughtExceptionHandler exceptionHandler; 66 67 68 public AsyncAnnotationBeanPostProcessor() { 69 setBeforeExistingAdvisors(true); 70 } 71 72 73 /** 74 * Set the 'async' annotation type to be detected at either class or method 75 * level. By default, both the {@link Async} annotation and the EJB 3.1 76 * {@code javax.ejb.Asynchronous} annotation will be detected. 77 * <p>This setter property exists so that developers can provide their own 78 * (non-Spring-specific) annotation type to indicate that a method (or all 79 * methods of a given class) should be invoked asynchronously. 80 * @param asyncAnnotationType the desired annotation type 81 */ 82 public void setAsyncAnnotationType(Class<? extends Annotation> asyncAnnotationType) { 83 Assert.notNull(asyncAnnotationType, "'asyncAnnotationType' must not be null"); 84 this.asyncAnnotationType = asyncAnnotationType; 85 } 86 87 /** 88 * Set the {@link Executor} to use when invoking methods asynchronously. 89 */ 90 public void setExecutor(Executor executor) { 91 this.executor = executor; 92 } 93 94 /** 95 * Set the {@link AsyncUncaughtExceptionHandler} to use to handle uncaught 96 * exceptions thrown by asynchronous method executions. 97 * @since 4.1 98 */ 99 public void setExceptionHandler(AsyncUncaughtExceptionHandler exceptionHandler) { 100 this.exceptionHandler = exceptionHandler; 101 } 102 103 @Override 104 public void setBeanFactory(BeanFactory beanFactory) { 105 AsyncAnnotationAdvisor advisor = new AsyncAnnotationAdvisor(this.executor, this.exceptionHandler); 106 if (this.asyncAnnotationType != null) { 107 advisor.setAsyncAnnotationType(this.asyncAnnotationType); 108 } 109 advisor.setBeanFactory(beanFactory); 110 this.advisor = advisor; 111 } 112 113 }