springboot异步和切面_Spring异步编程 | 你的@Async就真的异步吗?异步历险奇遇记

Spring异步编程 | 你的@Async就真的异步吗?异步历险奇遇记

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

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

06709019256fdb90068dddc1f00de3d7.png

引言有点长

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

44b3643f17bf893a1c4fe353f7aa8c02.png

且看下面的栗子:

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

3025f6df02aea4e3aa40278271d4e85e.png

今天就这点业务,我在暗想,这不是一个注解就搞掂的嘛~~~ 哈哈哈

94e24f3e9a43458419ca0dbac0751644.png

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

我的首发原创博客地址:你的@Async就真的异步吗 ☞ 异步历险奇遇记[1]

09ccf844a1fbefec5b0b76568fae28d0.png

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导致循环依赖问题的必要条件:

已开启@EnableAsync的支持

@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(Threa

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值