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 * @Configuration 040 * @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 * @Configuration 053 * public class AnotherAppConfig { 054 * 055 * @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 * @Configuration 086 * @EnableAsync 087 * public class AppConfig implements AsyncConfigurer { 088 * 089 * @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 * @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 — 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}