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(7); 093 * executor.setMaxPoolSize(42); 094 * executor.setQueueCapacity(11); 095 * executor.setThreadNamePrefix("MyExecutor-"); 096 * executor.initialize(); 097 * return executor; 098 * } 099 * 100 * @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 * <beans> 121 * 122 * <task:annotation-driven executor="myExecutor" exception-handler="exceptionHandler"/> 123 * 124 * <task:executor id="myExecutor" pool-size="7-42" queue-capacity="11"/> 125 * 126 * <bean id="asyncBean" class="com.foo.MyAsyncBean"/> 127 * 128 * <bean id="exceptionHandler" class="com.foo.MyAsyncUncaughtExceptionHandler"/> 129 * 130 * </beans> 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 — 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}