• 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"/>

  • 相关阅读:
    动词的形态及变化(转)
    数论基础
    P1505 [国家集训队]旅游
    贪心常见题
    主席树
    卡常火车头
    AC自动机
    左偏树
    位运算
    Linux下Vim常用操作
  • 原文地址:https://www.cnblogs.com/ark-blog/p/9028725.html
Copyright © 2020-2023  润新知