springboot实现异步调用的几种方式@Async失效

业务需求,用户下单后创建订单入库,并且发邮件及短信通知给发货人。由于前端在请求创建订单后需要拿到结果(成功/失败),并不关心短信及邮件的通知。所以通知的业务可以异步处理,不阻塞订单的创建,简单来说如果创建订单需要1秒,发送通知需要10秒,那么前端期望1秒之后拿到请求结果。而不是11秒。

在使用以下方法时,你需要确保Spring Boot应用的@EnableAsync注解已经开启,以启用Spring的异步支持。

解决方案1:使用@Async注解
先说一个错误用例,导致原因是@Async没有起到作用

//注意这是一个错误的用法,@Async没有起到作用
@Service
public class AsyncService {
 
    @Async
    public void executeAsyncTask() {
        // 执行异步逻辑 B
    }
 
    public void executeMainLogic() {
        // 执行主逻辑 A
 
        // 调用异步方法,并立即返回
        executeAsyncTask();
    }
}

原因分析
如果在一个类中,方法B被@Async修饰,而方法A没有被@Async修饰,并且方法A调用了方法B,那么会导致@Async修饰的方法B的注解失效。原因是,对于对于加了@Async的方法B是通过SpringAOP机制生成的代理类执行的,方法A是直接调用这个类的方法,因此通过A调用B,会使得B也被Spring当成普通方法直接调用,从而使得注解失效。
详细可参考

正确的方式应该这样写
(当然也可以将异步方法B的调用放在另外一个Bean上,并通过依赖注入的方式使用该Bean。)
因为我这里B方法的入参,有A方法返回的结果,所以是在一个方法中调用,具体可以根据自己的情况来定

@Service
public class AsyncService {
 
    @Async
    public void executeAsyncTask() {
        // 执行异步逻辑 B
    }
 
    public void executeMainLogic() {
        // 执行主逻辑 A
 
        // 调用异步方法,并立即返回,此处 SpringUtil 使用了hutool的包
        // import cn.hutool.extra.spring.SpringUtil;
        final AsyncService bean = SpringUtil.getApplicationContext().getBean(AsyncService.class);
        bean.executeAsyncTask();
    }
}

解决方案2:使用CompletableFuture

@Service
public class AsyncService {
 
    public void executeMainLogic() {
        // 执行主逻辑 A
 
        // 调用异步方法,并立即返回
        CompletableFuture.runAsync(this::executeAsyncTask);
    }
 
    public void executeAsyncTask() {
        // 执行异步逻辑 B
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值