我使用spring-boot-starter-parent 2.7.4
测试了一下,得到的结论是这样的: (我的切点的方法就是输出“汪汪汪”)
不使用@Around
通知:
before ...... 汪汪汪 afterReturning ...... after ......
使用@Around
通知:
around before...... before ...... 汪汪汪 afterReturning ...... after ...... around after......
按照网上的说法,应该顺序是这样的:around before
-> before
-> 切点方法
-> around after
-> after
-> after returning
为什么我的测试结果中afterReturning
竟然还跑到after
的前面去了, around after
跑到最后面去了?
我的@Aspect
代码`
@Aspect public class MyAspect { @Pointcut("execution(* com.example.springboot_test_1005.Dog.bark(..))") public void pointCut() { } @Before("pointCut()") public void before() { System.out.println("before ......"); } @After("pointCut()") public void after() { System.out.println("after ......"); } @AfterReturning("pointCut()") public void afterReturning() { System.out.println("afterReturning ......"); } @AfterThrowing("pointCut()") public void afterThrowing() { System.out.println("afterThrowing ......"); } @Around("pointCut()") public void around(ProceedingJoinPoint jp) throws Throwable { System.out.println("around before......"); // 回调目标对象的原有方法 jp.proceed(); System.out.println("around after......"); } }
被代理的类:
@Component public class Dog { void bark(){ System.out.println("汪汪汪"); } }
![]() | 1 movq OP |
2 optional 2022-10-09 14:05:33 +08:00 via iPhone 正常写代码依赖这个顺序不是把路走窄了吗。。 八股文问这个不去也罢 |
3 xy90321 2022-10-09 15:30:13 +08:00 ![]() |
4 xy90321 2022-10-09 15:41:22 +08:00 via iPhone ![]() @movq 看了下感觉是这个图不太对 虽然我好久不写切面了,不过根据文档来看 你最好把不同 advice 的优先度理解为一个 V 字模型 意味着 around 的 before 跑的最早 around 的 after 跑的最晚 这样才能确保 around 有最高优先级,可以 override 其他 advice 的处理 |
5 sumika 2022-10-09 16:46:39 +08:00 你找的网上的说法是 spring4 的顺序,代码里用的是 spring5 吧,这两个版本顺序不一样 |
![]() | 6 movq OP ![]() @xy90321 我也查了下,发现是图不对。csdn 上面瞎说的东西害死人。可以看这两个 github issue https://github.com/spring-projects/spring-framework/pull/24673 https://github.com/spring-projects/spring-framework/issues/25186 |
![]() | 8 threeroseing0 2022-10-10 09:32:35 +08:00 @movq 上述的 PR 应该是没有 Merge 的,可以看下 5.2.7 开始新增的注释 // Note: although @After is ordered before @AfterReturning and @AfterThrowing, // an @After advice method will actually be invoked after @AfterReturning and // @AfterThrowing methods due to the fact that AspectJAfterAdvice.invoke(MethodInvocation) // invokes proceed() in a `try` block and only invokes the @After advice method // in a corresponding `finally` bock. |
![]() | 9 movq OP @threeroseing0 那个 PR 被开发者看到了,然后开发者改了代码,逻辑和 PR 提出的要求是一样的: 上面第二个 github 连接里面最后一个 activity: jhoeller mentioned this issue on 3 Dec 2020 Clarify intended advice execution behavior in Spring version 5.2.7+ 点进去看代码是在 5.2.x 的代码里面的 |
10 nothingistrue 2022-10-10 10:41:32 +08:00 你网上的说法不对。第一,around before/after 必定与 before/after 对应出现,要么 around 在外,即 around before before after around after ,要么 around 在内,即 before around before around after after ,你网上那种顺序不符合常理 。第二,先执行方法后执行 after 切面,同时 return 是在方法内部的,所以 afterReturning 早于 after 更复合常规。 |