001/*
002 * Copyright 2002-2018 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.scheduling.annotation;
018
019import java.lang.annotation.Annotation;
020import java.lang.annotation.Documented;
021import java.lang.annotation.ElementType;
022import java.lang.annotation.Retention;
023import java.lang.annotation.RetentionPolicy;
024import java.lang.annotation.Target;
025
026import org.springframework.context.annotation.AdviceMode;
027import org.springframework.context.annotation.Configuration;
028import org.springframework.context.annotation.Import;
029import org.springframework.core.Ordered;
030
031/**
032 * Enables Spring's asynchronous method execution capability, similar to functionality
033 * found in Spring's {@code <task:*>} XML namespace.
034 *
035 * <p>To be used together with @{@link Configuration Configuration} classes as follows,
036 * enabling annotation-driven async processing for an entire Spring application context:
037 *
038 * <pre class="code">
039 * &#064;Configuration
040 * &#064;EnableAsync
041 * public class AppConfig {
042 *
043 * }</pre>
044 *
045 * {@code MyAsyncBean} is a user-defined type with one or more methods annotated with
046 * either Spring's {@code @Async} annotation, the EJB 3.1 {@code @javax.ejb.Asynchronous}
047 * annotation, or any custom annotation specified via the {@link #annotation} attribute.
048 * The aspect is added transparently for any registered bean, for instance via this
049 * configuration:
050 *
051 * <pre class="code">
052 * &#064;Configuration
053 * public class AnotherAppConfig {
054 *
055 *     &#064;Bean
056 *     public MyAsyncBean asyncBean() {
057 *         return new MyAsyncBean();
058 *     }
059 * }</pre>
060 *
061 * <p>By default, Spring will be searching for an associated thread pool definition:
062 * either a unique {@link org.springframework.core.task.TaskExecutor} bean in the context,
063 * or an {@link java.util.concurrent.Executor} bean named "taskExecutor" otherwise. If
064 * neither of the two is resolvable, a {@link org.springframework.core.task.SimpleAsyncTaskExecutor}
065 * will be used to process async method invocations. Besides, annotated methods having a
066 * {@code void} return type cannot transmit any exception back to the caller. By default,
067 * such uncaught exceptions are only logged.
068 *
069 * <p>To customize all this, implement {@link AsyncConfigurer} and provide:
070 * <ul>
071 * <li>your own {@link java.util.concurrent.Executor Executor} through the
072 * {@link AsyncConfigurer#getAsyncExecutor getAsyncExecutor()} method, and</li>
073 * <li>your own {@link org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler
074 * AsyncUncaughtExceptionHandler} through the {@link AsyncConfigurer#getAsyncUncaughtExceptionHandler
075 * getAsyncUncaughtExceptionHandler()}
076 * method.</li>
077 * </ul>
078 *
079 * <p><b>NOTE: {@link AsyncConfigurer} configuration classes get initialized early
080 * in the application context bootstrap. If you need any dependencies on other beans
081 * there, make sure to declare them 'lazy' as far as possible in order to let them
082 * go through other post-processors as well.</b>
083 *
084 * <pre class="code">
085 * &#064;Configuration
086 * &#064;EnableAsync
087 * public class AppConfig implements AsyncConfigurer {
088 *
089 *     &#064;Override
090 *     public Executor getAsyncExecutor() {
091 *         ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
092 *         executor.setCorePoolSize(7);
093 *         executor.setMaxPoolSize(42);
094 *         executor.setQueueCapacity(11);
095 *         executor.setThreadNamePrefix("MyExecutor-");
096 *         executor.initialize();
097 *         return executor;
098 *     }
099 *
100 *     &#064;Override
101 *     public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
102 *         return new MyAsyncUncaughtExceptionHandler();
103 *     }
104 * }</pre>
105 *
106 * <p>If only one item needs to be customized, {@code null} can be returned to
107 * keep the default settings. Consider also extending from {@link AsyncConfigurerSupport}
108 * when possible.
109 *
110 * <p>Note: In the above example the {@code ThreadPoolTaskExecutor} is not a fully managed
111 * Spring bean. Add the {@code @Bean} annotation to the {@code getAsyncExecutor()} method
112 * if you want a fully managed bean. In such circumstances it is no longer necessary to
113 * manually call the {@code executor.initialize()} method as this will be invoked
114 * automatically when the bean is initialized.
115 *
116 * <p>For reference, the example above can be compared to the following Spring XML
117 * configuration:
118 *
119 * <pre class="code">
120 * &lt;beans&gt;
121 *
122 *     &lt;task:annotation-driven executor="myExecutor" exception-handler="exceptionHandler"/&gt;
123 *
124 *     &lt;task:executor id="myExecutor" pool-size="7-42" queue-capacity="11"/&gt;
125 *
126 *     &lt;bean id="asyncBean" class="com.foo.MyAsyncBean"/&gt;
127 *
128 *     &lt;bean id="exceptionHandler" class="com.foo.MyAsyncUncaughtExceptionHandler"/&gt;
129 *
130 * &lt;/beans&gt;
131 * </pre>
132 *
133 * The above XML-based and JavaConfig-based examples are equivalent except for the
134 * setting of the <em>thread name prefix</em> of the {@code Executor}; this is because
135 * the {@code <task:executor>} element does not expose such an attribute. This
136 * demonstrates how the JavaConfig-based approach allows for maximum configurability
137 * through direct access to actual componentry.
138 *
139 * <p>The {@link #mode} attribute controls how advice is applied: If the mode is
140 * {@link AdviceMode#PROXY} (the default), then the other attributes control the behavior
141 * of the proxying. Please note that proxy mode allows for interception of calls through
142 * the proxy only; local calls within the same class cannot get intercepted that way.
143 *
144 * <p>Note that if the {@linkplain #mode} is set to {@link AdviceMode#ASPECTJ}, then the
145 * value of the {@link #proxyTargetClass} attribute will be ignored. Note also that in
146 * this case the {@code spring-aspects} module JAR must be present on the classpath, with
147 * compile-time weaving or load-time weaving applying the aspect to the affected classes.
148 * There is no proxy involved in such a scenario; local calls will be intercepted as well.
149 *
150 * @author Chris Beams
151 * @author Juergen Hoeller
152 * @author Stephane Nicoll
153 * @author Sam Brannen
154 * @since 3.1
155 * @see Async
156 * @see AsyncConfigurer
157 * @see AsyncConfigurationSelector
158 */
159@Target(ElementType.TYPE)
160@Retention(RetentionPolicy.RUNTIME)
161@Documented
162@Import(AsyncConfigurationSelector.class)
163public @interface EnableAsync {
164
165        /**
166         * Indicate the 'async' annotation type to be detected at either class
167         * or method level.
168         * <p>By default, both Spring's @{@link Async} annotation and the EJB 3.1
169         * {@code @javax.ejb.Asynchronous} annotation will be detected.
170         * <p>This attribute exists so that developers can provide their own
171         * custom annotation type to indicate that a method (or all methods of
172         * a given class) should be invoked asynchronously.
173         */
174        Class<? extends Annotation> annotation() default Annotation.class;
175
176        /**
177         * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
178         * to standard Java interface-based proxies.
179         * <p><strong>Applicable only if the {@link #mode} is set to {@link AdviceMode#PROXY}</strong>.
180         * <p>The default is {@code false}.
181         * <p>Note that setting this attribute to {@code true} will affect <em>all</em>
182         * Spring-managed beans requiring proxying, not just those marked with {@code @Async}.
183         * For example, other beans marked with Spring's {@code @Transactional} annotation
184         * will be upgraded to subclass proxying at the same time. This approach has no
185         * negative impact in practice unless one is explicitly expecting one type of proxy
186         * vs. another &mdash; for example, in tests.
187         */
188        boolean proxyTargetClass() default false;
189
190        /**
191         * Indicate how async advice should be applied.
192         * <p><b>The default is {@link AdviceMode#PROXY}.</b>
193         * Please note that proxy mode allows for interception of calls through the proxy
194         * only. Local calls within the same class cannot get intercepted that way; an
195         * {@link Async} annotation on such a method within a local call will be ignored
196         * since Spring's interceptor does not even kick in for such a runtime scenario.
197         * For a more advanced mode of interception, consider switching this to
198         * {@link AdviceMode#ASPECTJ}.
199         */
200        AdviceMode mode() default AdviceMode.PROXY;
201
202        /**
203         * Indicate the order in which the {@link AsyncAnnotationBeanPostProcessor}
204         * should be applied.
205         * <p>The default is {@link Ordered#LOWEST_PRECEDENCE} in order to run
206         * after all other post-processors, so that it can add an advisor to
207         * existing proxies rather than double-proxy.
208         */
209        int order() default Ordered.LOWEST_PRECEDENCE;
210
211}