原文地址:http://www.baeldung.com/spring-async

1. Overview

In this article we’ll explore the asynchronous execution support in Spring – and the @Async annotation.

Simply put – annotating a method of a bean with @Async will make it execute in a separate thread i.e. the caller will not wait for the completion of the called method.

2. Enable Async Support

Let’s start by enabling asynchronous processing with Java configuration – by simply adding the @EnableAsync to a configuration class:

1
2
3
@Configuration
@EnableAsync
public class SpringAsyncConfig { ... }

The enable annotation is enough, but as you’d expect, there are also a few simple options for configuration as well:

  • annotation – by default, @EnableAsync detects Spring’s @Async annotation and the EJB 3.1 javax.ejb.Asynchronous; this option can be used to detect other, user defined annotation types as well
  • mode – indicates the type of advice that should be used – JDK proxy-based or AspectJ weaving
  • proxyTargetClass – indicates the type of proxy that should be used – CGLIB or JDK; this attribute has effect only if the mode is set to AdviceMode.PROXY
  • order – sets the order in which AsyncAnnotationBeanPostProcessor should be applied; by default it runs last, just so that it can take into account all existing proxies

Asynchronous processing can also be enabled using XML configuration – by using the task namespace:

1
2
<task:executor id="myexecutor" pool-size="5"  />
<task:annotation-driven executor="myexecutor"/>

3. The @Async Annotation

First – let’s go over the rules – @Async has two limitations:

  • it must be applied to public methods only
  • self invocation – calling the async method from within the same class – won’t work

The reasons are simple – the method needs to be public so that it can be proxied. And self-invocation doesn’t work because it bypasses the proxy and calls the underlying method directly.

3.1. Methods with void Return Type

Following is the simple way to configure a method with void return type to run asynchronously:

1
2
3
4
5
@Async
public void asyncMethodWithVoidReturnType() {
    System.out.println("Execute method asynchronously. "
      + Thread.currentThread().getName());
}

3.2. Methods With Return Type

@Async can also be applied to a method with return type – by wrapping the actual return in a Future:

1
2
3
4
5
6
7
8
9
10
11
12
13
@Async
public Future<String> asyncMethodWithReturnType() {
    System.out.println("Execute method asynchronously - "
      + Thread.currentThread().getName());
    try {
        Thread.sleep(5000);
        return new AsyncResult<String>("hello world !!!!");
    } catch (InterruptedException e) {
        //
    }
    return null;
}

Spring also provides a AsyncResult class which implements Future. This can be used to track the result of asynchronous method execution.

Now, let’s invoke the above method and retrieve the result of the asynchronous process using the Future object.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public void testAsyncAnnotationForMethodsWithReturnType()
    throws InterruptedException, ExecutionException {
    System.out.println("Invoking an asynchronous method. "
      + Thread.currentThread().getName());
    Future<String> future = asyncAnnotationExample.asyncMethodWithReturnType();
    while (true) {
        if (future.isDone()) {
            System.out.println("Result from asynchronous process - " + future.get());
            break;
        }
        System.out.println("Continue doing something else. ");
        Thread.sleep(1000);
    }
}

4. The Executor

By default Spring uses a SimpleAsyncTaskExecutor to actually run these methods asynchronously. The defaults can be overridden at two levels – at the application level or at the individual method level.

4.1. Override the Executor at the Method Level

The required executor needs to be declared in a configuration class:

1
2
3
4
5
6
7
8
9
@Configuration
@EnableAsync
public class SpringAsyncConfig {
     
    @Bean(name = "threadPoolTaskExecutor")
    public Executor threadPoolTaskExecutor() {
        return new ThreadPoolTaskExecutor();
    }
}

Then the executor name should be provided as an attribute in @Async:

1
2
3
4
5
@Async("threadPoolTaskExecutor")
public void asyncMethodWithConfiguredExecutor() {
    System.out.println("Execute method with configured executor - "
      + Thread.currentThread().getName());
}

4.2. Override the Executor at the Application Level

The configuration class should implement the AsyncConfigurer interface – which will mean that it has the implement the getAsyncExecutor() method. It’s here that we will return the executor for the entire application – this now becomes the default executor to run methods annotated with @Async:

1
2
3
4
5
6
7
8
9
10
@Configuration
@EnableAsync
public class SpringAsyncConfig implements AsyncConfigurer {
     
    @Override
    public Executor getAsyncExecutor() {
        return new ThreadPoolTaskExecutor();
    }
     
}

5. Exception Handling

When a method return type is a Future, exception handling is easy – Future.get()method will throw the exception.

But, if the return type is voidexceptions will not be propagated to the calling thread. Hence we need to add extra configurations to handle exceptions.

We’ll create a custom async exception handler by implementingAsyncUncaughtExceptionHandler interface. The handleUncaughtException()method is invoked when there are any uncaught asynchronous exceptions:

1
2
3
4
5
6
7
8
9
10
11
12
public class CustomAsyncExceptionHandler  implements AsyncUncaughtExceptionHandler {
    @Override
    public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {
        System.out.println("Exception message - " + throwable.getMessage());
        System.out.println("Method name - " + method.getName());
        for (Object param : obj) {
            System.out.println("Parameter value - " + param);
        }
    }
     
}

In the previous section we looked at the AsyncConfigurer interface implemented by the configuration class. As part of that, we also need to override thegetAsyncUncaughtExceptionHandler() method to return our custom asynchronous exception handler:

1
2
3
4
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
    return new CustomAsyncExceptionHandler();
}

6. Conclusion

In this tutorial we looked at running asynchronous code with Spring. We started with the very basic configuration and annotation to make it work but also looked at more advanced configs such as providing our own executor, or exception handling strategies.

转载于:https://www.cnblogs.com/davidwang456/p/5685651.html

@Async in Spring--转相关推荐

  1. java 异步调用 事务_深入理解Spring注解@Async解决异步调用问题

    序言:Spring中@Async 根据Spring的文档说明,默认采用的是单线程的模式的.所以在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的. 那么当多个任务的执行势必会相互影响. ...

  2. Spring Boot 集成 Apollo 配置中心,真香、真强大!

    作者:超级小豆丁 来源:http://www.mydlq.club/article/42/ 由于 Apollo 概念比较多,刚开始使用比较复杂,最好先过一遍概念再动手实践尝试使用. 1.背景 随着程序 ...

  3. 一篇文章看懂@Scheduled定时器/@Async/CompletableFuture

    一篇文章看懂@Scheduled定时器/@Async/CompletableFuture @Scheduled注解解析: 1.cron:最重要的一个参数 cron表达式[秒] [分] [小时] [日] ...

  4. Spring教程– Spring Core Framework教程

    Spring is one of the most widely used Java EE frameworks. I have written a lot on Spring Tutorial an ...

  5. 异步处理函数async_Spring @Async异步处理注释

    异步处理函数async Spring @Async annotation allows us to create asynchronous methods in spring. Let's explo ...

  6. SpringBoot:快速使用Spring

    SpringBoot:快速使用Spirng 约定大于配置:很多配置springboot已经预设好了(和程序员达成约定); 特点:自动配置和起步依赖:依赖传递 spring解决企业级应用开发复杂性而创建 ...

  7. Spring Event + DDD = 王炸!!

    点击上方"芋道源码",选择"设为星标" 管她前浪,还是后浪? 能浪的浪,才是好浪! 每天 10:33 更新文章,每天掉亿点点头发... 源码精品专栏 原创 | ...

  8. spring web 知识点过一遍

    初始化spring mvc的工作 1.初始化Spring MVC的DispatcherServlet: 2.搭建转码过滤器,保证客户端请求进行正确地转码: 3.搭建视图解析器(view resolve ...

  9. 【Spring】Spring Framework Reference Documentation中文版18

    Part VI. The Web This part of the reference documentation covers Spring Framework's support for the ...

  10. Apollo 你了解下这些内容就完美了

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 来源:https://urlify.cn/eIBZne 前言 Ap ...

最新文章

  1. 深度详解ResNet到底在解决一个什么问题?
  2. linux shell mv/cp 错误: will not overwrite just-created <filename> with <sameFilename> 解决方法
  3. MySQL-MHA集群部署(binlog复制)
  4. python矩阵教程_numpy教程:矩阵matrix及其运算
  5. XSS攻击(出现的原因、预防措施......)
  6. Maven常用命令 - 构建反应堆中指定模块
  7. 河流干涸的原因可能是水循环被破坏
  8. VS工程下的tlb, tlh, tli文件说明(COM)
  9. 江苏省计算机二级vb样卷,江苏省计算机二级vb试题大全-20210327053658.docx-原创力文档...
  10. 网络安全/渗透测试工具AWVS14.9下载/使用教程/安装教程
  11. Python 猴子补丁
  12. cwRsync文件同步
  13. 安卓开发360扫描出现病毒“盗号木马”
  14. Angular动态绑定HTML文本
  15. Java对象内存空间大小计算
  16. android 7.1快捷方式App Shortcuts
  17. php获取搜索框的函数,PHP自定义函数获取搜索引擎来源关键字的方法
  18. SpringMVC图片文件上传功能实现
  19. 3.10 杭电复试题2012
  20. [小说连载]张小庆,在路上(8)- 要不要换工作

热门文章

  1. php服务为什么开不了,php怎么打不开
  2. 熟悉mysql基本数据库操作系统_MySQL数据库的基本操作
  3. spring boot第二讲
  4. 简书 java jvm_详细介绍Java虚拟机(JVM)
  5. 复杂查询练习_《从零学会SQL:简单查询》第二关 简单查询
  6. 2.5e2.0是合法的c语言常量,二级考试C语言程序设计.ppt
  7. 参考地、保护地、大地的概念
  8. 客户端升级为select模型
  9. python元组的创建取值排序计数_Python元组 tuple的概念与基本操作详解【定义、创建、访问、计数、推导式等】...
  10. java数据访问策略_java – 支持基于最近访问过的项目的高效启动策略的数据结构...