@EnableAsync
註解
要使用 @Async
,首先需要使用 @EnableAsync
註解開啟 Spring Boot 中的非同步特性。
@Configuration
@EnableAsync
public class AppConfig {
}
複製程式碼
更詳細的配置說明,可以參考:AsyncConfigurer
@Async
註解
支援的用法
(1)無入參無返回值方法
您可以用 @Async
註解修飾方法,這表明這個方法是非同步方式呼叫。換句話說,程式在呼叫此方法時會立即返回,而方法的實際執行發生在已提交給 Spring TaskExecutor
的任務中。在最簡單的情況下,您可以將註解應用於返回 void 的方法,如以下示例所示:
@Async
void doSomething() {
// this will be executed asynchronously
}
複製程式碼
(2)有入參無返回值方法
與使用 @Scheduled
註釋註釋的方法不同,這些方法可以指定引數,因為它們在執行時由呼叫者以“正常”方式呼叫,而不是由容器管理的排程任務呼叫。例如,以下程式碼是 @Async
註解的合法應用:
@Async
void doSomething(String s) {
// this will be executed asynchronously
}
複製程式碼
(3)有入參有返回值方法
甚至可以非同步呼叫返回值的方法。但是,這些方法需要具有 Future
型別的返回值。這仍然提供了非同步執行的好處,以便呼叫者可以在呼叫 Future
上的 get()
之前執行其他任務。以下示例顯示如何在返回值的方法上使用@Async
:
@Async
Future<String> returnSomething(int i) {
// this will be executed asynchronously
}
複製程式碼
不支援的用法
@Async
不能與生命週期回撥一起使用,例如 @PostConstruct
。
要非同步初始化 Spring bean,必須使用單獨的初始化 Spring bean,然後在目標上呼叫 @Async
帶註釋的方法,如以下示例所示:
public class SampleBeanImpl implements SampleBean {
@Async
void doSomething() {
// ...
}
}
public class SampleBeanInitializer {
private final SampleBean bean;
public SampleBeanInitializer(SampleBean bean) {
this.bean = bean;
}
@PostConstruct
public void initialize() {
bean.doSomething();
}
}
複製程式碼
明確指定執行器
預設情況下,在方法上指定 @Async
時,使用的執行器是在啟用非同步支援時配置的執行器,即如果使用 XML 或 AsyncConfigurer
實現(如果有),則為 annotation-driven
元素。但是,如果需要指示在執行給定方法時應使用預設值以外的執行器,則可以使用 @Async
註解的 value 屬性。以下示例顯示瞭如何執行此操作:
@Async("otherExecutor")
void doSomething(String s) {
// this will be executed asynchronously by "otherExecutor"
}
複製程式碼
在這種情況下,“otherExecutor”可以是 Spring 容器中任何 Executor bean 的名稱,也可以是與任何 Executor 關聯的限定符的名稱(例如,使用 <qualifier>
元素或 Spring 的 @Qualifier
註釋指定) )。
管理 @Async
的異常
當 @Async
方法的返回值型別為 Future
型時,很容易管理在方法執行期間丟擲的異常,因為在呼叫 get
結果時會丟擲此異常。但是,對於返回值型別為 void 型的方法,異常不會被捕獲且無法傳輸。您可以提供 AsyncUncaughtExceptionHandler
來處理此類異常。以下示例顯示瞭如何執行此操作:
public class MyAsyncUncaughtExceptionHandler implements AsyncUncaughtExceptionHandler {
@Override
public void handleUncaughtException(Throwable ex, Method method, Object... params) {
// handle exception
}
}
複製程式碼
預設情況下,僅記錄異常。您可以使用 AsyncConfigurer
或 <task:annotation-driven />
XML元素定義自定義 AsyncUncaughtExceptionHandler
。
示例
示例原始碼:spring-boot-async