@async 报错_Spring异步编程 | 你的@Async就真的异步吗?异步历险奇遇记

点击上方“java进阶架构师”,选择右上角“置顶公众号

20大进阶架构专题每日送达

7f3ba1d931ad15e286c42b83ab187037.png

引言有点长

前端的宝宝会用ajax,用异步编程到快乐的不行~ 我们java也有异步,用起来比他们还快乐~ 我们biaji一个注(gǒupí)解(gāoyào),也是快乐风男...

ba82fe2978da83e6a59c8d2576f64c8f.png且看下面的栗子:

注册一个用户,给他的账户初始化积分(也可以想象成注册奖励),再给用户发个注册通知短信,再发个邮件,(只是举栗子,切莫牛角大法),这样一个流程,短信和邮件我觉得完全可以拆分出来,没必要拖在在主流程上来(再补充上事务[ACID:原子性,一致性,隔离性,持久性]就好了):9e692ca12ec173894fa986ba4b7040fd.png今天就这点业务,我在暗想,这不是一个注解就搞掂的嘛~~~  哈哈哈

4a9736c4516a696c1da094a2f92cc206.png结果不是想象中的那么完美~~ 来看我的异(dind)步(ding)历险记b6ad1fa4b716a43c71073c3492c170d7.png

我的首发原创博客地址:你的@Async就真的异步吗 ☞ 异步历险奇遇记[1]   https://juejin.im/post/5d47a80a6fb9a06ad3470f9a 里面有gitHub项目地址,关注我,里面实战多多哦~


奇遇一 循环依赖异常

看code:

@Service
public class UserServiceImpl implements UserService {
@Autowired
UserService userService;

@Override
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
public int save(UserDTO userDTO) {
User user = new User();
BeanCopyUtils.copy(userDTO, user);
int insert = userMapper.insert(user);
System.out.println("User 保存用户成功:" + user);
userService.senMsg(user);
userService.senEmail(user);
return insert;
}

@Async
@Override
public Boolean senMsg(User user) {
try {
TimeUnit.SECONDS.sleep(2);
System.out.println("发送短信中:.....");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "给用户id:" + user.getId() + ",手机号:" + user.getMobile() + "发送短信成功");
return true;
}

@Async
@Override
public Boolean senEmail(User user) {
try {
TimeUnit.SECONDS.sleep(3);
System.out.println("发送邮件中:.....");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "给用户id:" + user.getId() + ",邮箱:" + user.getEmail() + "发送邮件成功");
return true;
}

结果:启动不起来,Spring循环依赖问题。 Spring不是解决了循环依赖问题吗,它是支持循环依赖的呀?怎么会呢?

不可否认,在这之前我也是这么坚信的,倘若你目前也和我有一样坚挺的想法,那就让异常UnsatisfiedDependencyException,has been injected into other beans [userServiceImpl] in its raw version as part of a circular reference,,来鼓励你,拥抱你, 就是这么的不给面子,赤裸裸的circular reference

谈到Spring Bean的循环依赖,有的小伙伴可能比较陌生,毕竟开发过程中好像对循环依赖这个概念无感知。其实不然,你有这种错觉,那是因为你工作在Spring的襁褓中,从而让你“高枕无忧”~ 其实我们的代码中肯定被我们写了循环依赖,比如像这样:

@Service
public class AServiceImpl implements AService {
@Autowired
private BService bService;
...
}
@Service
public class BServiceImpl implements BService {
@Autowired
private AService aService;
...
}

通过实验总结出,出现使用@Async导致循环依赖问题的必要条件:

  1. 已开启@EnableAsync的支持

  2. @Async注解所在的Bean被循环依赖了

奇遇二 异步失效异常

那么既然不能循环依赖,我们就不循环依赖,我们这么来:

@Service
public class UserServiceImpl implements UserService {
@Autowired
UserMapper userMapper;
@Autowired
SendService sendService;

@Override
@Transactional()
public int save(UserDTO userDTO) {
User user = new User();
BeanCopyUtils.copy(userDTO, user);
int insert = userMapper.insert(user);
System.out.println("User 保存用户成功:" + user);
this.senMsg(user);
this.senEmail(user);
return insert;
}


@Async
@Override
public Boolean senMsg(User user) {
System.out.println(Thread.currentThread().getName() + "给用户id:" + user.getId() + ",手机号:" + user.getMobile() + "发送短信成功");
return true;
}

@Async
@Override
public Boolean senEmail(User user) {
System.out.println(Thread.currentThread().getName() + "给用户id:" + user.getId() + ",邮箱:" + user.getEmail() + "发送邮件成功");
return true;
}

结果我们测试了几把,我打印一下结果:

2019-08-05 21:59:32.304  INFO 14360 --- [nio-8080-exec-3] com.alibaba.druid.pool.DruidDataSource   : {dataSource-1} inited
2019-08-05 21:59:32.346 DEBUG 14360 --- [nio-8080-exe
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值