MrDuck
MrDuck

Reputation: 23

Spring AOP runs in reveres order

I am currently experiencing something pretty weird. I have to Aspect classes, both of them have the same pointcut in an AfterThrowing tag. The Aspect classes are ordered, but always the lower priority one runs first, which I believe is the opposite of the expected behaviour.

@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
@Aspect
@Order(1)
public class AspectOne {

@AfterThrowing(pointcut = "exection(* com.test.*..*(..))", throwing = "ex")
public void doSomething(JoinPoint jp, Exception ex){
    System.out.println("AspectOne");
}

@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
@Aspect
@Order(2)
public class AspectTwo {

@AfterThrowing(pointcut = "exection(* com.test.*..*(..))", throwing = "ex")
public void doSomething(JoinPoint jp, Exception ex){
    System.out.println("AspectTwo");
}

According to the documentations, the smaller the number is, the higher the presedence is. Yet my output is:

If I switch the order, the result will also change. So The Order is working, but the opposite way it is supposed to. I tried with different numbers, the results are the same.

Upvotes: 0

Views: 166

Answers (1)

M. Deinum
M. Deinum

Reputation: 124556

The order works on the aspect and works as it should. However the after advices are executed in reverse order.

Imagine your aspects having both an @Before and @After

@Component
@Aspect
@Order(1)
public class AspectOne {

@Before(pointcut = "exection(* com.test.*..*(..))")
public void soSomethingBefore(Joinpoint jp) {
    System.out.println("[BEFORE] AspectOne");
}

@AfterThrowing(pointcut = "exection(* com.test.*..*(..))", throwing = "ex")
public void doSomething(JoinPoint jp, Exception ex){
    System.out.println("[AFTER ] AspectOne");
}

and

@Component
@Aspect
@Order(2)
public class AspectTwo {

@Before(pointcut = "exection(* com.test.*..*(..))")
public void soSomethingBefore(Joinpoint jp) {
    System.out.println("[BEFORE] AspectTwo");
}

@AfterThrowing(pointcut = "exection(* com.test.*..*(..))", throwing = "ex")
public void doSomething(JoinPoint jp, Exception ex){
    System.out.println("[AFTER ] AspectTwo");
}

If you would look at the output it would be

[BEFORE] AspectOne
[BEFORE] AspectTwo
[AFTER ] AspectTwo
[AFTER ] AspeectOne

So the ordering is honored however you have to take into consideration that after advices are in the reverse order.

You might wonder why?

Lets take an @Around advice which is basically an @Before and an @After advice. If the first aspect would be about starting a transaction, it should be the last to commit/rollback the transaction, as everything in between should participate in the same transaction. If it would be the first to start and commit other parts of the execution wouldn't be part of the tx, possibly leading to weird issues.

NOTE: Please remove the @Configuration and @EnableAspectJAutoProxy just create 1 config class that does this, and make your aspects regular @Component classes.

Upvotes: 3

Related Questions