Spring异步方法支持—@Async

  背景:前几周,公司的一个项目须要发送邮件,起初并无考虑时间的影响,就未采用同步的方式进行发送。到了测试环境,发现须要发送邮件的地方耗时太久,所以研究了一下spring的异步方法支持—@Async,发现效果不错,在这里分享下。java

  使用场景: 用于保证任务的及时性 ,适用于某一段耗时过长的代码,例如发送短信、邮件、调用第三方接口等等...  spring

 

1、开启异步支持异步

  <!-- 异步任务线程池 -->async

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

  注意: @Async、@Transactional等注解采用的是代理模式,若是在同一个类的某个方法上,调用本类带有@Async等注解的方法是,该注解会失效。spa

 

2、 @Async用法线程

1. 注解应用范围:代理

  类: 若是该注解应用在类上,表示该类全部方法是异步的code

  方法: 若是该注解应用在方法上,表示该方法是异步的blog

 

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");
}

 

3、 @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"/>

相关文章
相关标签/搜索