最近刚接触 springboot 切面编程的相关内容,有个问题网上没太找到相关的解答,想问一下家人们~ 我现在定义了一个 @AfterReturning 的方法,在这个方法我执行了一个线程休眠 10 秒的操作。 但是我调用加入这个切点的方法时,为什么是需要调用 10 秒才能返回呀,这个 @AfterReturning 不是在方法执行完成返回结果之后执行的么? 相关代码如下:
@Pointcut("@annotation(com.ice.hilf.contentmoderation.annotation.PicModeration)")
public void picPointcut() {}
@AfterReturning(pointcut = "picPointcut()", returning = "result")
public void doAfterReturning(JoinPoint joinPoint, Object result) throws InterruptedException {
System.out.println("Start aop");
// 休眠,等待图片压缩完成
Thread.sleep(10 * 1000);
System.out.println("End sleep");
}
Controller 层方法上加上切面注解
@PicModeration
@PostMapping("/upload")
@ResponseBody
public ApiResponse<UniFileRtnVO> upload(
@RequestParam("file")MultipartFile file,
@RequestParam(value = "uploadType", required = false)Byte uploadType,
@RequestParam("fileType") Byte fileType){
...
return ApiResponse.success(rtnVO);
}
实际测试时结果就是每次调用这个接口要等 10s 才有返回值,是不是我对 @AfterReturning 的执行原理理解的有问题啊
1
BBCCBB 2022-06-02 11:40:36 +08:00
你 debug 一下, 在你的 afterReturing 里断点, 然后看一下线程执行堆栈.
|
2
XhstormR02 2022-06-02 11:41:11 +08:00 via Android
不是多线程,如果你想让浏览器立即获取接口结果,你应该 hook tomcat 的方法
|
3
iosyyy 2022-06-02 11:51:11 +08:00
Thread.sleep(10 * 1000); 会挂起当前线程吧 所以不会返回 你新开一个线程用 future 来做异步返回的操作
|
4
iosyyy 2022-06-02 11:52:14 +08:00
而且你这操作应该用延时队列好一点吧
|
5
LeegoYih 2022-06-02 12:12:50 +08:00
切面是通过动态代理实现的,可以简单的理解为把代码包了一层,大致执行流程如下:
1. aop.before() 2. res = controller.upload(); 3. aop.after() 4. return res 你在第 3 步睡了 10 秒,HTTP 接口也就会被 block 10 秒,因为他们用的是同一个线程执行的。 |
6
OldCarMan 2022-06-02 12:32:14 +08:00
个人觉得,spring aop 是通过一个代理对象来完成切面编程的过程的,无论是这个过程的哪个步骤( Around...AfterThrowing )最终都是统一到这个代理对象中的方法一步步去完成这个过程的,这个过程是在同一个线程中完成的,你调用 Thread.sleep(10 * 1000),相当于在这个代理对象的方法中让当前线程休眠 10 秒钟,肯定是无法达到你“方法返回后休眠 10 秒钟”的需求的,简单的话建议使用异步队列的方式去完成你的需求。
|
7
fanxasy 2022-06-02 14:13:53 +08:00
你想要的是 @After ,不是 @AfterReturning
|