SpringBoot之异步执⾏⽅法
前⾔:
最近的时候遇到⼀个需求,就是当服务器接到请求并不需要任务执⾏完成才返回结果,可以⽴即返回结果,让任务异步的去执⾏。开始考虑是直接启⼀个新的线程去执⾏任务或
者把任务提交到⼀个线程池去执⾏,这两种⽅法都是可以的。但是Spring 这么强⼤,肯定有什么更简单的⽅法,就 google 了⼀下,还真有呢。就是使⽤ @EnableAsync 和
@Async 这两个注解就 ok 了。
给⽅法加上 @Async 注解
package me.deweixu.aysncdemo.service;
public interface AsyncService {
void asyncMethod(String arg);
}
package me.deweixu.aysncdemo.service.ipml;
import me.deweixu.aysncdemo.service.AsyncService;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
@Service
public class AsyncServiceImpl implements AsyncService {
@Async
@Override
public void asyncMethod(String arg) {
System.out.println("arg:" + arg);
System.out.println("=====" + Thread.currentThread().getName() + "=========");
}
}
@EnableAsync
在启动类或者配置类加上 @EnableAsync 注解
package me.deweixu.aysncdemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
@EnableAsync
@SpringBootApplication
public class AysncDemoApplication {
public static void main(String[] args) {
SpringApplication.run(AysncDemoApplication.class, args);
}
}
测试
package me.deweixu.aysncdemo;
import me.deweixu.aysncdemo.service.AsyncService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.st.context.SpringBootTest;
import st.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class AysncDemoApplicationTests {
@Autowired
AsyncService asyncService;
@Test
public void testAsync() {
System.out.println("=====" + Thread.currentThread().getName() + "=========");
asyncService.asyncMethod("Async");
}
}
=====main=========
2018-03-25 21:30:31.391 INFO 28742 --- [ main] .s.a.AnnotationAsyncExecutionInterceptor : No task executor bean found for async processing: no bean of type TaskExecutor and no bean named 'taskExecutor' either arg:Async
=====SimpleAsyncTaskExecutor-1=========
从上⾯的结果看 asyncService.asyncMethod("Async") 确实异步执⾏了,它使⽤了⼀个新的线程。
指定 "Executor"
从上⾯执⾏的⽇志可以猜测到 Spring 默认使⽤ SimpleAsyncTaskExecutor 来异步执⾏任务的,可以搜索到这个类。 @Async 也可以指定⾃定义的 Executor。在启动类中增加⾃定义的 Executor
package me.deweixu.aysncdemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import t.annotation.Bean;
import org.springframework.scheduling.annotation.EnableAsync;
import org.urrent.ThreadPoolTaskExecutor;
import urrent.Executor;
@EnableAsync
@SpringBootApplication
public class AysncDemoApplication {
public static void main(String[] args) {
SpringApplication.run(AysncDemoApplication.class, args);
}
springboot原理流程@Bean(name = "threadPoolTaskExecutor")
public Executor threadPoolTaskExecutor() {
return new ThreadPoolTaskExecutor();
}
}
指定 "Executor"
package me.deweixu.aysncdemo.service.ipml;
import me.deweixu.aysncdemo.service.AsyncService;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
@Service
public class AsyncServiceImpl implements AsyncService {
@Async("threadPoolTaskExecutor")
@Override
public void asyncMethod(String arg) {
System.out.println("arg:" + arg);
System.out.println("=====" + Thread.currentThread().getName() + "=========");
}
}
这样在异步执⾏任务的时候就使⽤ threadPoolTaskExecutor
设置默认的
Executor
上⾯提到如果 @Async 不指定 Executor 就默认使⽤ SimpleAsyncTaskExecutor,其实默认的 Executor 是可以使⽤ AsyncConfigurer 接⼝来配置的
@Configuration
public class SpringAsyncConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
return new ThreadPoolTaskExecutor();
}
}
异常捕获
在异步执⾏的⽅法中是可能出现异常的,我们可以在任务内部使⽤ try catch 来处理异常,当任务抛出异常时, Spring 也提供了捕获它的⽅法。
实现 AsyncUncaughtExceptionHandler 接⼝
public class CustomAsyncExceptionHandler
implements AsyncUncaughtExceptionHandler {
@Override
public void handleUncaughtException(
Throwable throwable, Method method, obj) {
System.out.println("Exception message - " + Message());
System.out.println("Method name - " + Name());
for (Object param : obj) {
System.out.println("Parameter value - " + param);
}
}
}
实现 AsyncConfigurer 接⼝重写 getAsyncUncaughtExceptionHandler ⽅法
@Configuration
public class SpringAsyncConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
return new ThreadPoolTaskExecutor();
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new CustomAsyncExceptionHandler();
}
}
改写 asyncMethod ⽅法使它抛出异常
@Async
@Override
public void asyncMethod(String arg) {
System.out.println("arg:" + arg);
System.out.println("=====" + Thread.currentThread().getName() + "========="); throw new NullPointerException();
}
运⾏结果:
=====main=========
arg:Async
=====threadPoolTaskExecutor-1=========
Exception message - Async NullPointerException
Method name - asyncMethod
Parameter value - Async
正确捕获到了异常。
我是⼩架,我们
下篇⽂章见!

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。