SpringBoot Async
Hướng dẫn Spring Boot về xử lý yêu cầu bất đồng bộ
Chú thích @EnableAsync
Để sử dụng @Async
, trước tiên cần sử dụng chú thích @EnableAsync
để bật tính năng bất đồng bộ trong Spring Boot.
@Configuration
@EnableAsync
public class AppConfig {
}
Để biết thêm chi tiết về cấu hình, bạn có thể tham khảo: AsyncConfigurer
Chú thích @Async
Các cách sử dụng được hỗ trợ
(1) Phương thức không có tham số và không có giá trị trả về
Bạn có thể sử dụng chú thích @Async
để đánh dấu phương thức này là phương thức được gọi bất đồng bộ. Nói cách khác, khi chương trình gọi phương thức này, nó sẽ trả về ngay lập tức, trong khi việc thực thi phương thức xảy ra trong tác vụ đã được gửi đến TaskExecutor
của Spring. Trong trường hợp đơn giản nhất, bạn có thể áp dụng chú thích này cho phương thức trả về void, như ví dụ dưới đây:
@Async
void doSomething() {
// phần này sẽ được thực thi bất đồng bộ
}
(2) Phương thức có tham số nhưng không có giá trị trả về
Khác với việc sử dụng chú thích @Scheduled
, các phương thức này có thể chỉ định các tham số vì chúng được gọi bởi người gọi theo cách "bình thường" trong thời gian chạy, chứ không phải là bởi các tác vụ lập lịch được quản lý bởi container. Ví dụ, đoạn mã dưới đây là một ứng dụng hợp lệ của chú thích @Async
:
@Async
void doSomething(String s) {
// phần này sẽ được thực thi bất đồng bộ
}
(3) Phương thức có tham số và có giá trị trả về
Bạn cũng có thể gọi bất đồng bộ các phương thức trả về giá trị. Tuy nhiên, các phương thức này cần có kiểu trả về là Future
. Điều này vẫn cung cấp lợi ích của việc thực thi bất đồng bộ để người gọi có thể thực hiện các nhiệm vụ khác trước khi gọi get()
trên Future
. Ví dụ dưới đây cho thấy cách sử dụng @Async
trên phương thức trả về giá trị:
@Async
Future<String> returnSomething(int i) {
// phần này sẽ được thực thi bất đồng bộ
}
Các cách sử dụng không được hỗ trợ
@Async
không thể được sử dụng cùng với các gọi lại vòng đời như @PostConstruct
.
Để khởi tạo bất đồng bộ bean Spring, bạn phải sử dụng một bean khởi tạo riêng biệt và sau đó gọi phương thức được chú thích @Async
trên mục tiêu, như ví dụ dưới đây:
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();
}
}
Xác định rõ bộ thực thi
Mặc định, khi chú thích @Async
trên phương thức, bộ thực thi được sử dụng là bộ thực thi được cấu hình khi bật hỗ trợ bất đồng bộ, tức là nếu sử dụng XML hoặc AsyncConfigurer
(nếu có). Tuy nhiên, nếu bạn cần chỉ định một bộ thực thi khác ngoài giá trị mặc định khi thực thi phương thức cụ thể, bạn có thể sử dụng thuộc tính value của chú thích @Async
. Ví dụ dưới đây cho thấy cách thực hiện điều này:
@Async("otherExecutor")
void doSomething(String s) {
// phần này sẽ được thực thi bất đồng bộ bởi "otherExecutor"
}
Trong trường hợp này, "otherExecutor" có thể là tên của bất kỳ bean Executor nào trong container Spring, hoặc là tên của bất kỳ qualifier nào liên quan đến bất kỳ Executor nào (ví dụ: sử dụng phần tử <qualifier>
hoặc chú thích @Qualifier
của Spring).
Quản lý ngoại lệ của @Async
Khi kiểu trả về của phương thức @Async
là kiểu Future
, quản lý ngoại lệ xảy ra trong quá trình thực thi phương thức rất dễ dàng, vì ngoại lệ sẽ được ném ra khi gọi get()
kết quả. Tuy nhiên, đối với các phương thức trả về kiểu void, ngoại lệ không được bắt và không thể truyền đi. Bạn có thể cung cấp AsyncUncaughtExceptionHandler
để xử lý các ngoại lệ này. Ví dụ dưới đây cho thấy cách thực hiện điều này:
public class MyAsyncUncaughtExceptionHandler implements AsyncUncaughtExceptionHandler {
@Override
public void handleUncaughtException(Throwable ex, Method method, Object... params) {
// xử lý ngoại lệ
}
}
Mặc định, chỉ ghi lại ngoại lệ. Bạn có thể xác định AsyncUncaughtExceptionHandler
tùy chỉnh bằng cách sử dụng AsyncConfigurer
hoặc phần tử <task:annotation-driven />
trong XML.
Mã nguồn ví dụ
Mã nguồn ví dụ: spring-boot-async