异步任务spring @Async注解源码解析

1.引子开启异步任务使用方法:1).方法上加@Async注解 2).启动类或者配置类上@EnableAsync2.源码解析虽然spring5已经出来了,但是我们还是使用的spring4,本文就根据spring-context-4.3.14.RELEASE.jar来分析源码。2.1.@Async org.springframework.scheduling.annotat...
摘要由CSDN通过智能技术生成

1.引子

开启异步任务使用方法:

1).方法上加@Async注解 

2).启动类或者配置类上@EnableAsync

2.源码解析

虽然spring5已经出来了,但是我们还是使用的spring4,本文就根据spring-context-4.3.14.RELEASE.jar来分析源码。

2.1.@Async

org.springframework.scheduling.annotation.Async 源码注释翻译:

 1 /**
 2  * Annotation that marks a method as a candidate for <i>asynchronous</i> execution.
 3  * Can also be used at the type level, in which case all of the type's methods are
 4  * considered as asynchronous.该注解可以标记一个异步执行的方法,也可以用来标注类,表示类中的所有方法都是异步执行的。
 5  *
 6  * <p>In terms of target method signatures, any parameter types are supported.
 7  * However, the return type is constrained to either {
    @code void} or
 8  * {
    @link java.util.concurrent.Future}. In the latter case, you may declare the
 9  * more specific {
    @link org.springframework.util.concurrent.ListenableFuture} or
10  * {
    @link java.util.concurrent.CompletableFuture} types which allow for richer
11  * interaction with the asynchronous task and for immediate composition with
12  * further processing steps.入参随意,但返回值只能是void或者Future.(ListenableFuture接口/CompletableFuture类)
13 * 14 * <p>A { @code Future} handle returned from the proxy will be an actual asynchronous 15 * { @code Future} that can be used to track the result of the asynchronous method 16 * execution. However, since the target method needs to implement the same signature, 17 * it will have to return a temporary { @code Future} handle that just passes a value 18 * through: e.g. Spring's { @link AsyncResult}, EJB 3.1's { @link javax.ejb.AsyncResult}, 19 * or { @link java.util.concurrent.CompletableFuture#completedFuture(Object)}. 20 * Future是代理返回的切实的异步返回,用以追踪异步方法的返回值。当然也可以使用AsyncResult类(实现ListenableFuture接口)(Spring或者EJB都有)或者CompletableFuture类 21 * @author Juergen Hoeller 22 * @author Chris Beams 23 * @since 3.0 24 * @see AnnotationAsyncExecutionInterceptor 25 * @see AsyncAnnotationAdvisor 26 */ 27 @Target({ElementType.METHOD, ElementType.TYPE}) 28 @Retention(RetentionPolicy.RUNTIME) 29 @Documented 30 public @interface Async { 31 32 /** 33 * A qualifier value for the specified asynchronous operation(s). 34 * <p>May be used to determine the target executor to be used when executing this 35 * method, matching the qualifier value (or the bean name) of a specific 36 * { @link java.util.concurrent.Executor Executor} or 37 * { @link org.springframework.core.task.TaskExecutor TaskExecutor} 38 * bean definition.用以限定执行方法的执行器名称(自定义):Executor或者TaskExecutor 39 * <p>When specified on a class level { @code @Async} annotation, indicates that the 40 * given executor should be used for all methods within the class. Method level use 41 * of { @code Async#value} always overrides any value set at the class level. 42 * @since 3.1.2 加在类上表示整个类都使用,加在方法上会覆盖类上的设置 43 */ 44 String value() default ""; 45 46 }

上图源码注释已经写的很清晰了哈,主要注意3点:

1)返回值:不要返回值直接void;需要返回值用AsyncResult或者CompletableFuture

2)可自定义执行器并指定例如:@Async("otherExecutor")

3)@Async  必须不同类间调用: A类--》B类.C方法()(@Async注释在B类/方法中),如果在同一个类中调用,会变同步执行,例如:A类.B()-->A类.@Async C(),原因是:底层实现是代理对注解扫描实现的,B方法上没有注解,没有生成相应的代理类。(当然把@Async加到类上也能解决但所有方法都异步了,一般不这么用!)

2.2 @EnableAsync

老规矩咱们直接看类注释:

//开启spring异步执行器,类似xml中的task标签配置,需要联合@Configuration注解一起使用
Enables Spring's asynchronous method execution capability, similar to functionality found in Spring's <task:*> XML namespace.
To be used together with @Configuration classes as follows, enabling annotation-driven async processing for an entire Spring application context:
 @Configuration
 @EnableAsync
 public class AppConfig {

 }
MyAsyncBean is a user-defined type with one or more methods annotated with either Spring's @Async annotation, the EJB 3.1 @javax.ejb.Asynchronous annotation, or any custom annotation specified via the annotation() attribute. The aspect is added transparently for any registered bean, for instance via this configuration:
 @Configuration
 public class AnotherAppConfig {

     @Bean
     public MyAsyncBean asyncBean() {
         return new MyAsyncBean();
     }
 }

//默认情况下spring会先搜索TaskExecutor类型的bean或者名字为taskExecutor的Executor类型的bean,都不存在使用SimpleAsyncTaskExecutor执行器
By default, Spring will be searching for an associated thread pool definition: either a unique TaskExecutor bean in the context, or an Executor bean named "taskExecutor" otherwise. If neither of the two is resolvable, a SimpleAsyncTaskExecutor will be used to process async method invocations. Besides, annotated methods having a void return type cannot transmit any exception back to the caller. By default, such uncaught exceptions are only logged.
To customize all this, implement AsyncConfigurer and provide:
your own Executor through the getAsyncExecutor() method, and your own AsyncUncaughtExceptionHandler through the getAsyncUncaughtExceptionHandler() method.//可实现AsyncConfigurer接口复写getAsyncExecutor获取异步执行器,getAsyncUncaughtExceptionHandler获取异步未捕获异常处理器
 @Configuration
 @EnableAsync
 public class AppConfig implements AsyncConfigurer {

     @Override
     public Executor getAsyncExecutor() {
         ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
         executor.setCorePoolSize(7);
         executor.setMaxPoolSize(42);
         executor.setQueueCapacity(11);
         executor.setThreadNamePrefix("MyExecutor-");
         executor.initialize();
         return executor;
     }

     @Override
     public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
         return MyAsyncUncaughtExceptionHandler();
     }
 }
If only one item needs to be customized, null can be returned to keep the default settings. Consider also extending from AsyncConfigurerSupport when possible.
Note: In the above example the ThreadPoolTaskExecutor is not a fully managed Spring bean. Add the @Bean annotation to the getAsyncExecutor() method if you want a fully managed bean. In such circumstances it is no longer necessary to manually call the executor.initialize() method as this will be invoked automatically when the bean is initialized.
For reference, the example above can be compared to the following Spring XML configuration:
 <beans>

     <task:annotation-driven e

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值