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(5);
093 *         executor.setMaxPoolSize(10);
094 *         executor.setQueueCapacity(25);
095 *         executor.setThreadNamePrefix("MyExecutor-");
096 *         executor.initialize();
097 *         return executor;
098 *     }
099 *
100 *     &#064;Override
101 *     public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
102 *         return 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 * {@code
121 * <beans>
122 *
123 *     <task:annotation-driven executor="myExecutor" exception-handler="exceptionHandler"/>
124 *
125 *     <task:executor id="myExecutor" pool-size="5-10" queue-capacity="25"/>
126 *
127 *     <bean id="asyncBean" class="com.foo.MyAsyncBean"/>
128 *
129 *     <bean id="exceptionHandler" class="com.foo.MyAsyncUncaughtExceptionHandler"/>
130 *
131 * </beans>
132 * }</pre>
133 *
134 * The above XML-based and JavaConfig-based examples are equivalent except for the
135 * setting of the <em>thread name prefix</em> of the {@code Executor}; this is because
136 * the {@code <task:executor>} element does not expose such an attribute. This
137 * demonstrates how the JavaConfig-based approach allows for maximum configurability
138 * through direct access to actual componentry.
139 *
140 * <p>The {@link #mode} attribute controls how advice is applied: If the mode is
141 * {@link AdviceMode#PROXY} (the default), then the other attributes control the behavior
142 * of the proxying. Please note that proxy mode allows for interception of calls through
143 * the proxy only; local calls within the same class cannot get intercepted that way.
144 *
145 * <p>Note that if the {@linkplain #mode} is set to {@link AdviceMode#ASPECTJ}, then the
146 * value of the {@link #proxyTargetClass} attribute will be ignored. Note also that in
147 * this case the {@code spring-aspects} module JAR must be present on the classpath, with
148 * compile-time weaving or load-time weaving applying the aspect to the affected classes.
149 * There is no proxy involved in such a scenario; local calls will be intercepted as well.
150 *
151 * @author Chris Beams
152 * @author Juergen Hoeller
153 * @author Stephane Nicoll
154 * @author Sam Brannen
155 * @since 3.1
156 * @see Async
157 * @see AsyncConfigurer
158 * @see AsyncConfigurationSelector
159 */
160@Target(ElementType.TYPE)
161@Retention(RetentionPolicy.RUNTIME)
162@Documented
163@Import(AsyncConfigurationSelector.class)
164public @interface EnableAsync {
165
166        /**
167         * Indicate the 'async' annotation type to be detected at either class
168         * or method level.
169         * <p>By default, both Spring's @{@link Async} annotation and the EJB 3.1
170         * {@code @javax.ejb.Asynchronous} annotation will be detected.
171         * <p>This attribute exists so that developers can provide their own
172         * custom annotation type to indicate that a method (or all methods of
173         * a given class) should be invoked asynchronously.
174         */
175        Class<? extends Annotation> annotation() default Annotation.class;
176
177        /**
178         * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
179         * to standard Java interface-based proxies.
180         * <p><strong>Applicable only if the {@link #mode} is set to {@link AdviceMode#PROXY}</strong>.
181         * <p>The default is {@code false}.
182         * <p>Note that setting this attribute to {@code true} will affect <em>all</em>
183         * Spring-managed beans requiring proxying, not just those marked with {@code @Async}.
184         * For example, other beans marked with Spring's {@code @Transactional} annotation
185         * will be upgraded to subclass proxying at the same time. This approach has no
186         * negative impact in practice unless one is explicitly expecting one type of proxy
187         * vs. another &mdash; for example, in tests.
188         */
189        boolean proxyTargetClass() default false;
190
191        /**
192         * Indicate how async advice should be applied.
193         * <p><b>The default is {@link AdviceMode#PROXY}.</b>
194         * Please note that proxy mode allows for interception of calls through the proxy
195         * only. Local calls within the same class cannot get intercepted that way; an
196         * {@link Async} annotation on such a method within a local call will be ignored
197         * since Spring's interceptor does not even kick in for such a runtime scenario.
198         * For a more advanced mode of interception, consider switching this to
199         * {@link AdviceMode#ASPECTJ}.
200         */
201        AdviceMode mode() default AdviceMode.PROXY;
202
203        /**
204         * Indicate the order in which the {@link AsyncAnnotationBeanPostProcessor}
205         * should be applied.
206         * <p>The default is {@link Ordered#LOWEST_PRECEDENCE} in order to run
207         * after all other post-processors, so that it can add an advisor to
208         * existing proxies rather than double-proxy.
209         */
210        int order() default Ordered.LOWEST_PRECEDENCE;
211
212}