SpringBoot 教程之處理非同步請求

靜默虛空發表於2019-05-09

@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

參考資料

相關文章