我使用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 1
|
4
xy90321 2022-10-09 15:41:22 +08:00 via iPhone 1
@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` block. |
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 更复合常规。
|