View Javadoc
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 }