Spring异步编程

异步&同步

最常见的一个场景是用户注册后,需要发送注册邮件和短信通知,以告知用户注册成功。传统的做法有以下两种:

同步

同步方式下的注册流程如下图所示。


同步方式.png

数据流动如下所述:

  • 用户在注册页面填写账号和密码并提交注册信息,这些注册信息首先会被写入注册系统成功。
  • 注册信息写入注册系统成功后,再发送请求至邮件通知系统。邮件通知系统收到请求后向用户发送邮件通知。
  • 邮件通知系统接收注册系统请求后再向下游的短信通知系统发送请求。短信通知系统收到请求后向用户发送短信通知。

异步

异步方式下的注册流程如下图所示。


异步方式.png

数据流动如下所述:

  • 用户在注册页面填写账号和密码并提交注册信息,这些注册信息首先会被写入注册系统成功。
  • 注册信息写入注册系统成功后,再同时发送请求至邮件和短信通知系统。邮件和短信通知系统收到请求后分别向用户发送邮件和短信通知。

Spring异步

@Async

异步的方法有3种

  • 最简单的异步调用,返回值为void
  • 带参数的异步调用 异步方法可以传入参数
  • 异常调用返回Future
@Component
public class AsyncDemo {

    /**
     * 最简单的异步调用,返回值为void
     */
    @Async
    public void asyncInvokeSimplest() {
       //逻辑
    }

    /**
     * 带参数的异步调用 异步方法可以传入参数
     * 
     * @param s
     */
    @Async
    public void asyncInvokeWithParameter(String s) {
        //逻辑
    }

    /**
     * 异常调用返回Future
     * 
     * @param i
     * @return
     */
    @Async
    public Future asyncInvokeReturnFuture() {
        //逻辑
        Future future;
        try {
            future = new AsyncResult("async success");
        } catch (InterruptedException e) {
            future = new AsyncResult("async error");
        }
        return future;
    }

}

异步注解失效

  • 异步嵌套调用,第二个异步注解失效。
@Component
public class AsyncDemoA {
    @Autowired      
    private AsyncDemoB asyncDemoB 
    @Async
    public void asyncInvokeSimplestA() {
       //逻辑
      //此时B 的异步注解会失效
       asyncDemoB.asyncInvokeSimplestB();
    }
   
}
@Component
public class AsyncDemoB {
    @Async
    public void asyncInvokeSimplestB() {
       //逻辑
    }
   
}
  • 类中方法的引用。
@Component
public class AsyncDemoA {
    @Async
    public void asyncInvokeSimplestA() {
       //逻辑
    }
   
    public void test() {
       //逻辑
      //此时A 的异步注解会失效
       this.asyncInvokeSimplestA();
    }
}

注意事项

  • 尽量不要在本类中异步调用
  • 尽量不要有返回值
  • 不能使用本类的私有方法或者非接口化加注@Async,因为代理不到失效
  • 异步方法不能使用static修饰
  • 如果使用SpringBoot框架必须在启动类中增加@EnableAsync注解

spring异步原理

分析

  • spring 在扫描bean的时候会扫描方法上是否包含@Async的注解,如果包含的,spring会为这个bean动态的生成代理类。
  • spring自己维护了一个队列,他会把需要执行的方法,放入队列中,等待线程池去读取这个队列,完成方法的执行, 从而完成了异步的功能。

你可能感兴趣的:(Spring异步编程)