Spring異步方法支持—@Async


  背景:前幾周,公司的一個項目需要發送郵件,起初並沒有考慮時間的影響,就未采用同步的方式進行發送。到了測試環境,發現需要發送郵件的地方耗時過久,因此研究了一下spring的異步方法支持—@Async,發現效果不錯,在這里分享下。

  使用場景: 用於保證任務的及時性 ,適用於某一段耗時過長的代碼,例如發送短信、郵件、調用第三方接口等等...  

 

一、開啟異步支持

  <!-- 異步任務線程池 -->

  <task:annotation-driven executor="asyncExecutor"/>
  <task:executor id="asyncExecutor" pool-size="5-20" queue-capacity="5"/>

  注意: @Async、@Transactional等注解采用的是代理模式,如果在同一個類的某個方法上,調用本類帶有@Async等注解的方法是,該注解會失效。

 

二、 @Async用法

1. 注解應用范圍:

  類: 如果該注解應用在類上,表示該類所有方法是異步的

  方法: 如果該注解應用在方法上,表示該方法是異步的

 

2. 基於無返回值的調用 

public void resetPassword() {
    System.out.println("#resetPassword() - reset password start...");
    smsHandler.send1();
    System.out.println("#resetPassword() - reset password end...");
}

@Async("asyncExecutor")
public void send1() {
    Thread.sleep(5000);
    System.out.println("#notice1() - notice end...");
}

 

3. 基於@Async帶返回值的調用

public void resetPassword() {
    Future<String> future = smsHandler.send2();
    System.out.println(future.isDone());
}

@Async("asyncExecutor")
public Future<String> send2() {
    Thread.sleep(5000);
    return new AsyncResult<String>("send success");
}

 

三、 @Async的異常處理

  如果是基於有返回值的調用,可通過Futrue進行異常的封裝。如果是無返回值得調用,異常將無法被捕獲和傳遞。Spring提供了AsyncUncaughtExceptionHandler接口進行該類問題的處理,默認的實現是 org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler, 我們可以也可以實現AsyncUncaughtExceptionHandler,實現自己項目需要的異常處理。

1. 自定義異常處理類

@Component("unbenAsyncUncaughtExceptionHandler")
public class UnbenAsyncUncaughtExceptionHandler implements AsyncUncaughtExceptionHandler {

    private static final Logger logger = LoggerFactory.getLogger(UnbenAsyncUncaughtExceptionHandler.class);
    
    /* (non-Javadoc)
     * @see org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler#handleUncaughtException(java.lang.Throwable, java.lang.reflect.Method, java.lang.Object[])
     */
    public void handleUncaughtException(Throwable ex, Method method, Object... params) {

        logger.error("#handleUncaughtException() - exception=[{}], method=[{}], params=[{}]", 
                ex.getMessage(), method.getDeclaringClass() + "#" + method.getName(), StringUtils.join(params, ", "));
        
    }

}

 

2. 配置

  <task:annotation-driven executor="asyncExecutor" exception-handler="unbenAsyncUncaughtExceptionHandler"/>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM