详解Spring Boot 异步执行方法
最近遇到一个需求,就是当服务器接到请求并不需要任务执行完成才返回结果,可以立即返回结果,让任务异步的去执行。开始考虑是直接启一个新的线程去执行任务或者把任务提交到一个线程池去执行,这两种方法都是可以的。但是Spring这么强大,肯定有什么更简单的方法,就google了一下,还真有呢。就是使用@EnableAsync和@Async这两个注解就ok了。
给方法加上@Async注解
packageme.deweixu.aysncdemo.service;
publicinterfaceAsyncService{
voidasyncMethod(Stringarg);
}
packageme.deweixu.aysncdemo.service.ipml;
importme.deweixu.aysncdemo.service.AsyncService;
importorg.springframework.scheduling.annotation.Async;
importorg.springframework.stereotype.Service;
@Service
publicclassAsyncServiceImplimplementsAsyncService{
@Async
@Override
publicvoidasyncMethod(Stringarg){
System.out.println("arg:"+arg);
System.out.println("====="+Thread.currentThread().getName()+"=========");
}
}
@EnableAsync
在启动类或者配置类加上@EnableAsync注解
packageme.deweixu.aysncdemo;
importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.SpringBootApplication;
importorg.springframework.scheduling.annotation.EnableAsync;
@EnableAsync
@SpringBootApplication
publicclassAysncDemoApplication{
publicstaticvoidmain(String[]args){
SpringApplication.run(AysncDemoApplication.class,args);
}
}
测试
packageme.deweixu.aysncdemo;
importme.deweixu.aysncdemo.service.AsyncService;
importorg.junit.Test;
importorg.junit.runner.RunWith;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.boot.test.context.SpringBootTest;
importorg.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
publicclassAysncDemoApplicationTests{
@Autowired
AsyncServiceasyncService;
@Test
publicvoidtestAsync(){
System.out.println("====="+Thread.currentThread().getName()+"=========");
asyncService.asyncMethod("Async");
}
}
=====main=========
2018-03-2521:30:31.391 INFO28742---[ main].s.a.AnnotationAsyncExecutionInterceptor:Notaskexecutorbeanfoundforasyncprocessing:nobeanoftypeTaskExecutorandnobeannamed'taskExecutor'either
arg:Async
=====SimpleAsyncTaskExecutor-1=========
从上面的结果看asyncService.asyncMethod("Async")确实异步执行了,它使用了一个新的线程。
指定Executor
从上面执行的日志可以猜测到Spring默认使用SimpleAsyncTaskExecutor来异步执行任务的,可以搜索到这个类。@Async也可以指定自定义的Executor。
在启动类中增加自定义的Executor
packageme.deweixu.aysncdemo;
importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.SpringBootApplication;
importorg.springframework.context.annotation.Bean;
importorg.springframework.scheduling.annotation.EnableAsync;
importorg.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
importjava.util.concurrent.Executor;
@EnableAsync
@SpringBootApplication
publicclassAysncDemoApplication{
publicstaticvoidmain(String[]args){
SpringApplication.run(AysncDemoApplication.class,args);
}
@Bean(name="threadPoolTaskExecutor")
publicExecutorthreadPoolTaskExecutor(){
returnnewThreadPoolTaskExecutor();
}
}
指定Executor
packageme.deweixu.aysncdemo.service.ipml;
importme.deweixu.aysncdemo.service.AsyncService;
importorg.springframework.scheduling.annotation.Async;
importorg.springframework.stereotype.Service;
@Service
publicclassAsyncServiceImplimplementsAsyncService{
@Async("threadPoolTaskExecutor")
@Override
publicvoidasyncMethod(Stringarg){
System.out.println("arg:"+arg);
System.out.println("====="+Thread.currentThread().getName()+"=========");
}
}
这样在异步执行任务的时候就使用threadPoolTaskExecutor
设置默认的Executor
上面提到如果@Async不指定Executor就默认使用SimpleAsyncTaskExecutor,其实默认的Executor是可以使用AsyncConfigurer接口来配置的
@Configuration
publicclassSpringAsyncConfigimplementsAsyncConfigurer{
@Override
publicExecutorgetAsyncExecutor(){
returnnewThreadPoolTaskExecutor();
}
}
异常捕获
在异步执行的方法中是可能出现异常的,我们可以在任务内部使用trycatch来处理异常,当任务抛出异常时,Spring也提供了捕获它的方法。
实现AsyncUncaughtExceptionHandler接口
publicclassCustomAsyncExceptionHandler
implementsAsyncUncaughtExceptionHandler{
@Override
publicvoidhandleUncaughtException(
Throwablethrowable,Methodmethod,Object...obj){
System.out.println("Exceptionmessage-"+throwable.getMessage());
System.out.println("Methodname-"+method.getName());
for(Objectparam:obj){
System.out.println("Parametervalue-"+param);
}
}
}
实现AsyncConfigurer接口重写getAsyncUncaughtExceptionHandler方法
@Configuration
publicclassSpringAsyncConfigimplementsAsyncConfigurer{
@Override
publicExecutorgetAsyncExecutor(){
returnnewThreadPoolTaskExecutor();
}
@Override
publicAsyncUncaughtExceptionHandlergetAsyncUncaughtExceptionHandler(){
returnnewCustomAsyncExceptionHandler();
}
}
改写asyncMethod方法使它抛出异常
@Async
@Override
publicvoidasyncMethod(Stringarg){
System.out.println("arg:"+arg);
System.out.println("====="+Thread.currentThread().getName()+"=========");
thrownewNullPointerException();
}
运行结果:
=====main=========
arg:Async
=====threadPoolTaskExecutor-1=========
Exceptionmessage-AsyncNullPointerException
Methodname-asyncMethod
Parametervalue-Async
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。