Springboot @AfterReturning 线程休眠的问题

2022-06-02 11:25:30 +08:00
 MioZhang

最近刚接触 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 的执行原理理解的有问题啊

1506 次点击
所在节点    Java
7 条回复
BBCCBB
2022-06-02 11:40:36 +08:00
你 debug 一下, 在你的 afterReturing 里断点, 然后看一下线程执行堆栈.
XhstormR02
2022-06-02 11:41:11 +08:00
不是多线程,如果你想让浏览器立即获取接口结果,你应该 hook tomcat 的方法
iosyyy
2022-06-02 11:51:11 +08:00
Thread.sleep(10 * 1000); 会挂起当前线程吧 所以不会返回 你新开一个线程用 future 来做异步返回的操作
iosyyy
2022-06-02 11:52:14 +08:00
而且你这操作应该用延时队列好一点吧
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 秒,因为他们用的是同一个线程执行的。
OldCarMan
2022-06-02 12:32:14 +08:00
个人觉得,spring aop 是通过一个代理对象来完成切面编程的过程的,无论是这个过程的哪个步骤( Around...AfterThrowing )最终都是统一到这个代理对象中的方法一步步去完成这个过程的,这个过程是在同一个线程中完成的,你调用 Thread.sleep(10 * 1000),相当于在这个代理对象的方法中让当前线程休眠 10 秒钟,肯定是无法达到你“方法返回后休眠 10 秒钟”的需求的,简单的话建议使用异步队列的方式去完成你的需求。
fanxasy
2022-06-02 14:13:53 +08:00
你想要的是 @After ,不是 @AfterReturning

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/856891

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX