@Async注解不生效

一、起因

今天宝发现一个后台保存接口响应时间过长,发现是我们一个异步操作没有生效, 原本一段代码加了@Async注解应该异步执行的,但是最后查看日志是同步的,导致接口响应超时。

二、复现

由于内部代码不好透露,这里模拟了一个例子

2.1保存接口

/**
*保存接口
**/
@Override
public void save() {
	//按照本意这两个时间应该相差无几
	log.info(LocalDateTime.now().toString(); .
	for(inti= 0;i< 3;i++){
		asyncSave(;
	}
	log.info(LocalDateTime.now().toString);
}
/**
*异步线程模拟保存数据库方法假设执行5s
*/
@Override
@Async(" asyncServiceExecutor")
public void asyncSave() {
	try {
	Thread.sleep(5000);
	} catch (InterruptedException e) {
	e.printStackTrace();
	}
}

2.2打印结果

2022-01-14 14:58:58.138 INFO 1072--- [main] com.pingan.hht.service.OrderServiceImpl : 2022-01-14T14:58:58.138
2022-01-14 14:59:13.140 INFO 1072 --- [main] com.pingan.hht.service.OrderServiceImpl : 2022-01-14T14:59:13.140

2.3小结

原本按照我们的想法,这两个输出时间应该是一致的, 但是却前后相差15秒之多,那么究竟是为何如此呢?我们又该如何达成最初的目的?

三、分析

其实问题很明显,对spring了解的宝应该一眼就能看出问题在哪。这个和注解@Transactional不生效场景 样,我们知道spring注解生效实质是AOP,AOP实质是生成一个代理对象对目标方法进行增强,而这个asyncSave()在调用处是直接调用的,也就是等价于this.asyncSave() 普通调用方法方式,spring说我怎么知道你要AOP啊。所以我们解决的方式就是告诉spring我们要用的是代理对象的方法,不是这个呆呆的方法。但是有些宝说你说的我都不信,好好好~,图给你
@Async注解不生效_第1张图片

3.1方式一(亲测可用,不是本次讨论重点)

将这个方法写到其他service中如OtherService,然后在通过@Autoware注入调用处改成otherSevice. asyncSave()

3.2方式二(重点讨论)

方式一还要特地写到别的service中,嗯~,我这个人有点固执,明明是属于这个类的方法,放到别的类中,不OOP了嘛,所以方式二就是在当前类中注入自身,然后自身调用。对spring了解的宝又会说了,你这样不就会有循环引用问题了嘛,果然是我的宝,真聪明。没错这样确实会有循环弓用的问题。
1.出现循环引用

Bean with name 'orderServiceImpl' has been injected into other beans [orderServiceImpl] in its raw version as part of a circular reference, but has eventually been
wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using
'getBeanNamesOfType' with the 'llowEagerInit' flag turned off, for example.

这个时候,稳了,完了,巴比q了,程序启动不了了。.
2.解决循环引用
别着急,有我在,只需要在注入的地方加上@Lazy注解。如果你有时间的话可以跟一下异常的代码, 就能找到这个问题如何解决,还会对spring的bean创建流程有所了解,这个也不是本次讨论的重点,就略过了,咳咳~。(哼, 渣男! )

@Lazy
@Autowired
private OrderService orderService;

3.咱们继续试一把

2022-01-14 16:03:18.106 INFO 112200 -- [main] com. pingan.hht . service. OrderServiceImpl : 2022-01-14T16:03:18. 105
2022-01-14 16:03:18.110 INFO 112200 --- [main] com. pingan. hht . service. OrderServiceImpl : 2022-01-14T16:03:18.110

可以看到时间几乎没差,也就说明我们的异步方法执行成功了。

@Async注解不生效_第2张图片
可以对比一下之前的栈帧图。宝此时露出了崇拜的表情。

四、告辞

宝,这次补课就到这里了,下次再见。

你可能感兴趣的:(线上问题,spring,java,后端)