Home > Mobile >  Spring AOP different advice execution order?
Spring AOP different advice execution order?

Time:10-09

I used spring-boot-starter-parent 2.7.4 to test the execution sequence of @Around @Before @After @AfterReturning,here is what I got: (The method of my point cut is to print "hello, world")

If I do not use @Around advice:

    before ......
    hello, world
    afterReturning ......
    after ......

If I use @Around advice:

    around before......
    before ......
    hello, world
    afterReturning ......
    after ......
    around after......

According to the Internet, the sequence should be:around before -> before -> join point method -> around after -> after -> after returning

Why in my result, afterReturning went ahead of after, and around after went to the end?

My @Aspect code

@Aspect
@Component
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("hello, world");
        }
    }

CodePudding user response:

The result you got is correct, according to Spring documentation:

Around advice: Advice that surrounds a join point such as a method invocation. This is the most powerful kind of advice. Around advice can perform custom behavior before and after the method invocation. It is also responsible for choosing whether to proceed to the join point or to shortcut the advised method execution by returning its own return value or throwing an exception.

You can change the order of execution by excluding an advice to another class annotate those Aspect classes with @Order as shown below:

@Aspect
@Component
@Order(1)
public class MyAspect {
  @Pointcut("execution(* com.example.springboot_test_1005.Dog.bark(..))")
  public void pointCut() {
  }

  @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 ......");
  }
}
@Aspect
@Component
@Order(2)
public class MyAspect2 {
  @Pointcut("execution(* com.example.springboot_test_1005.Dog.bark(..))")
  public void pointCut() {
  }

  @Around("pointCut()")
  public void around(ProceedingJoinPoint jp) throws Throwable {
    System.out.println("around before......");
    jp.proceed();
    System.out.println("around after......");
  }
}
@Aspect
@Component
@Order(3)
public class MyAspect3 {
  @Pointcut("execution(* com.example.springboot_test_1005.Dog.bark(..))")
  public void pointCut() {
  }

  @Before("pointCut()")
  public void before() {
    System.out.println("before ......");
  }
}

In that case, the output would be:

around before......
before ......
helloWorld
around after......
afterReturning ......
after ......

CodePudding user response:

According to the Internet, the sequence should be:around before -> before -> join point method -> around after -> after -> after returning

The answer on the Internet is wrong.

After searching more similar questions, I found out that

  1. Order according to Spring Documentation

As of Spring Framework 5.2.7, advice methods defined in the same @Aspect class that need to run at the same join point are assigned precedence based on their advice type in the following order, from highest to lowest precedence: @Around, @Before, @After, @AfterReturning, @AfterThrowing. Note, however, that an @After advice method will effectively be invoked after any @AfterReturning or @AfterThrowing advice methods in the same aspect, following AspectJ’s "after finally advice" semantics for @After.

  1. Relevant github issues:
  • Related