如何在 Spring 中使用 async

如何在 Spring 中使用 async


搬运自:https://www.baeldung.com/spring-async

  1. 概述
    在本教程中,我们将探索 Spring 中的异步执行支持和@Async 注释。

简单地说,使用@Async 注释 bean 的方法将使它在单独的线程中执行。换句话说,调用方不会等待被调用方法的完成。

Spring 中一个有趣的方面是,如果需要,框架中的事件支持也支持异步处理。

进一步阅读:

Spring 中的事件基础——创建一个简单的自定义事件,发布它并在侦听器中处理它。
阅读更多 →
使用@Async 进行 Spring 安全上下文传播
使用@Async 注释时传播 Spring Security 上下文的一个简短示例
阅读更多 →
支持 Spring MVC 和 Spring Security 的 Servlet 3异步
对 springmvc 中支持异步请求的 springsecurity 的快速介绍。
阅读更多 →
2. 启用异步支持
让我们从使用 Java 配置启用异步处理开始。

我们将通过将@EnableAsync 添加到一个配置类来实现:

@Configuration
@EnableAsync
public class SpringAsyncConfig { … }
启用注释已经足够了,但是还有一些简单的配置选项:

注释——默认情况下,@enableasync 检测 Spring 的@Async 注释和 EJB 3.1 javax.EJB。异步的。我们还可以使用此选项检测其他用户定义的注释类型。
模式指示应该使用的通知类型ー基于 JDK 代理或 AspectJ 编织。
proxyTargetClass 指示应该使用的代理类型ーー CGLIB 或 JDK。此属性只有在模式设置为 AdviceMode.PROXY 时才有效。
Order 设置 AsyncAnnotationBeanPostProcessor 应用的顺序。默认情况下,它最后运行,以便能够考虑到所有现有的代理。
我们也可以通过使用任务名称空间启用 XML 配置的异步处理:

<task:executor id=“myexecutor” pool-size=“5” />
<task:annotation-driven executor=“myexecutor”/>
3.@async 注释
首先,让我们回顾一下规则:

它只能应用于公共方法。
自调用(Self-invocation)ーー从同一个类中调用异步方法ーー不会起作用。
原因很简单: 方法需要公开,这样它才能被代理。自调用不起作用,因为它绕过代理并直接调用底层方法。

3.1. 带 Void Return 类型的方法
这是一个简单的配置方法,带有 void 返回类型来异步运行:

@Async
public void asyncMethodWithVoidReturnType() {
System.out.println("Execute method asynchronously. "
+ Thread.currentThread().getName());
}
3.2. 带返回类型的方法
我们也可以将@Async 应用到带有返回类型的方法中,方法是将实际返回包装在 Future 中:

@Async
public Future asyncMethodWithReturnType() {
System.out.println("Execute method asynchronously - "
+ Thread.currentThread().getName());
try {
Thread.sleep(5000);
return new AsyncResult(“hello world !!!”);
} catch (InterruptedException e) {
//
}

return null;

}
Spring 还提供了一个 AsyncResult 类来实现 Future。我们可以用它来跟踪异步方法执行的结果。

现在,让我们调用上述方法并使用 Future 对象检索异步流程的结果。

public void testAsyncAnnotationForMethodsWithReturnType()
throws InterruptedException, ExecutionException {
System.out.println("Invoking an asynchronous method. "
+ Thread.currentThread().getName());
Future 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. 遗嘱执行人
默认情况下,Spring 使用 SimpleAsyncTaskExecutor 来实际异步运行这些方法。但是,我们可以在两个级别上覆盖缺省值: 应用程序级别或单个方法级别。

4.1. 在方法级别重写执行器
我们需要在配置类中声明所需的执行器:

@Configuration
@EnableAsync
public class SpringAsyncConfig {

@Bean(name = "threadPoolTaskExecutor")
public Executor threadPoolTaskExecutor() {
    return new ThreadPoolTaskExecutor();
}

}
然后我们应该在@Async 中提供这个 executor 名称作为属性:

@Async(“threadPoolTaskExecutor”)
public void asyncMethodWithConfiguredExecutor() {
System.out.println("Execute method with configured executor - "
+ Thread.currentThread().getName());
}
4.2. 在应用程序级别覆盖执行器
配置类应该实现 asyncconfigureer 接口。因此,它必须实现 getAsyncExecutor ()方法。在这里,我们将退还整个申请的执行人。这现在成为运行带有@Async 注释的方法的默认执行器:

@Configuration
@EnableAsync
public class SpringAsyncConfig implements AsyncConfigurer {

@Override
public Executor getAsyncExecutor() {
    return new ThreadPoolTaskExecutor();
}

}
5. 异常处理
当方法返回类型是 Future 时,异常处理很容易。

但是,如果返回类型是 void,则异常将不会传播到调用线程。因此,我们需要添加额外的配置来处理异常。

我们将通过实现 AsyncUncaughtExceptionHandler 接口创建一个定制的异步异常处理程序。当存在未捕获的异步异常时,调用 handleUncaughtException ()方法:

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);
    }
}

}
在前面的部分中,我们介绍了配置类实现的 asyncconfigureer 接口。作为其中的一部分,我们还需要覆盖 getAsyncUncaughtExceptionHandler ()方法来返回我们自定义的异步异常处理程序:

@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new CustomAsyncExceptionHandler();
}
6. 总结
在本文中,我们讨论了如何使用 Spring 运行异步代码。

我们从最基本的配置和注释开始,使其工作。但是我们也考虑了更高级的信任,比如提供我们自己的执行者或异常处理策略。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值