1 весенняя версия
5.1.4.RELEASE
2 Основное использование
2.1 Включить поддержку асинхронных задач
@EnableAsync
а также@Configuration
классы вместе, как показано ниже, чтобы включить асинхронную обработку на основе аннотаций для всего контекста приложения Spring.
@Configuration
@EnableAsync
public class AppConfig {
}
2.2 Написание асинхронных задач
@Component
public class EmailService {
@Async
//无返回类型
public void send(String from, String to, String subject, String text) {
//do send
}
@Async
//有返回类型
public Future<String> send(String from, String to, String subject, String text) {
System.out.println("Execute method asynchronously - "
+ Thread.currentThread().getName());
try {
Thread.sleep(5000);
return new AsyncResult<String>("hello world !!!!");
} catch (InterruptedException e) {
//
}
return null;
}
}
когда мы звонимsend()
метод, задача будет выполняться асинхронно,@Async
Его можно использовать не только на методах, но и на классах Bean, если все методы в классе асинхронные
3 Пользовательский исполнитель
По умолчанию Spring будет искать связанное определение пула потоков: единственное в контекстеTaskExecutor bean
, или другое имя "taskExecutor"Executor bean
. Если ни один из них не поддается разбору, он будет использоватьсяSimpleAsyncTaskExecutor
Обработка вызовов асинхронных методов. Кроме того, сvoid
Аннотированные методы возвращаемых типов не могут отправлять какие-либо исключения обратно вызывающей стороне. По умолчанию регистрируются только такие необработанные исключения.
Чтобы настроить все это, нужно реализоватьAsyncConfigurer
и предоставить:
- настроить
Executor
: пройти черезgetAsyncExecutor()
реализация метода - настроить
AsyncUncaughtExceptionHandler
: пройти черезgetAsyncUncaughtExceptionHandler()
реализовать
Уведомление:AsyncConfigurer
Классы конфигурации инициализируются на ранней стадии начальной загрузки контекста приложения. если у вас есть другиеbean
есть какие-либо зависимости, обязательно объявите их какLazy
, чтобы пропустить их через другие постпроцессоры.
@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.setWaitForTasksToCompleteOnShutdown(true);//默认是false,即shutdown时会立即停止并终止当前正在执行任务
executor.setRejectedExecutionHandler((r, executor1) -> {
for(;;) {
try {
executor1.getQueue().put(r);
} catch (InterruptedException e) {
e.printStackTrace();
}
return;
}
});//指定被拒绝任务的处理方法,经过测试当并发量超过队列长度时可以继续执行,否则会抛出 org.springframework.core.task.TaskRejectedException异常
executor.initialize();
return executor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new CustomAsyncExceptionHandler();//自定义未捕获异常处理,参考 4 异常处理 小节
}
}
3.1 Настройка Executor на уровне метода
Приведенное выше переписывает Executor на уровне приложения, а Spring также обеспечивает переписывание на уровне методов: Включите Async и настройте Executor:
@Configuration
@EnableAsync
public class SpringAsyncConfig {
@Bean(name = "threadPoolTaskExecutor")
public Executor threadPoolTaskExecutor() {
return new ThreadPoolTaskExecutor();
}
}
Используйте пользовательский Executor
@Async("threadPoolTaskExecutor")
public void asyncMethodWithConfiguredExecutor() {
System.out.println("Execute method with configured executor - "
+ Thread.currentThread().getName());
}
4 Обработка исключений
Когда тип возвращаемого значения методаFuture
Обработка исключений проста — метод Future.get() выдает исключение.
Однако если возвращаемый тип недействителен, исключение не распространяется на вызывающий поток. Поэтому нам нужно добавить дополнительную конфигурацию для обработки исключений.
Мы добьемся путем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);
}
}
}
5 принципов
В общем, Spring использует технологию АОП для реализации асинхронных задач, и подробные принципы будут описаны позже.