譯者:littlebrain4solving
來源:
https://blog.csdn.net/littlebrain4solving/
概要說明
在此篇文章中,我們根據使用@Async注解進行探索Spring對異步執行的支持。
簡單的把@Async注解放到Bean的方法上就會使用不同的線程運行,也就是說,調用者執行此方法不用一直等待整個方法執行完畢。
在Spring中比較有趣的一點就是事件機制也支持異步處理,如果你想這樣使用的話。
配置并開啟@Async掃描支持
讓我們開始使用JAVA的注解配置開啟異步處理機制,只需要簡單的加上@EnableAsync注解到配置類上即可。
@Configuration
@EnableAsync
public class SpringAsyncConfig { ... }
通過加上簡單的注解基本就滿足需要了,但如果你有其它需要,依然也有幾種簡單選項供你設置:
- annotation:默認情況下, @EnableAsync 會掃描使用了Spring @Async與EJB 3.1 javax.ejb.Asynchronous的方法;此選項也可以用來掃描其他的,如用戶自定義的注解類型;
- mode:指定應該使用哪種AOP進行切面處理 - JAVA代理或AspectJ;
- proxyTargetClass:指定應該使用哪種代理類 - CGLIB或JDK;此屬性只有當mode設置成AdviceMode.PROXY才會產生效果。
- order:設置AsyncAnnotationBeanPostProcessor執行順序(生命周期有關);默認情況下會最后一個執行,所以這樣就能顧及到所有已存在的代理。
異步處理方式配置也可以使用XML進行配置,通過使用task的namespace。
<task:executor id="myexecutor" pool-size="5" />
<task:annotation-driven executor="myexecutor"/>
關于@Async注解
首先 - 讓我們來了解一些規則 - @Async有兩點局限性(無法正常工作)。
- 方法名必須是public進行修飾的
- 必須不能在同一個類中調用異步方法
原因很簡單:方法名必須用public修飾才能被進行代理;而同一個類中調用方法的話會略過代理進行直接調用。
方法無返回值
下例就是一個簡單的無返回值的異步運行方法:
@Async
public void asyncMethodWithVoidReturnType() {
System.out.println("Execute method asynchronously. "
+ Thread.currentThread().getName());
}
方法有返回值
@Async 注解的方法也可以指定返回類型:只需在Future的泛型中指定所需要返回的類型即可。

Spring 同樣也提供了一個Future的實現類叫AsyncResult,此類可以用來跟蹤異步方法調用結果。
現在,讓我們來調用上面的方法并通過Future進行獲取到異步處理的結果。

關于Executor
默認情況下,Spring使用SimpleAsyncTaskExecutor來運行這些異步方法,默認的設置方式可以在兩個層級上面進行覆蓋 - 在應用全局配置上或在單獨的方法上。
單獨的方法上覆蓋Executor
在配置類中配置所需的executor:

應用全局配置上覆蓋Executor
配置類應該實現AsyncConfigurer接口 - 意思是getAsyncExecutor方法需要我們自己來進行實現,會返回Executor給整個應用實例使用 - 意味著現在充當默認的Executor去運行加了@Async注解的方法。

異常處理
由于返回值類型是Future,異常處理就簡單了 - Future.get()會拋出異常。
但是,如果返回類型是void,異常將無法正常傳送到調用的線程. 因此,我們需要添加一些額外的配置來處理異常。
我們創建一個實現了
AsyncUncaughtExceptionHandler接口的自定義異步異常處理類.一旦任意未捕獲的異常產生后都會調用handleUncaughtException()方法。

在上一個代碼段中,我們看到配置類實現了AsyncConfigurer接口.根據其中的部分,我們同樣也需要實現
getAsyncUncaughtExceptionHandler()方法來自定義我們的異步異常處理類:
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new CustomAsyncExceptionHandler();
}
結論
在本章中,我們看到利用Spring運行一個異步任務只需要配置一些很簡單的內容就可以達到效果了,但我們同樣也看到更多高級的配置用法,如:自定義Executor或自定義異常處理策略。
然后,和往常一樣,本文中出現的代碼在Github中可以查看,
https://github.com/eugenp/tutorials/tree/master/spring-all
原文出處
http://www.baeldung.com/spring-async