首先先贴个总结比较好的一个博客:Spring AOP @Before @Around @After 等 advice 的执行顺序。但是其中有个错误,异常情况下,method执行完会直接执行@After 方法,而不会再执行@Around 后面的代码。所以,其中的图是有问题的。
1.1 正常情况:
public interface Person {
String sayHello(String name);
void eat(String food);
}
@Component
public class Chinese implements Person {
@Timer
@Override
public String sayHello(String name) {
System.out.println("-- sayHello() --");
return name + " hello, AOP";
}
@Override
public void eat(String food) {
System.out.println("我正在吃:" + food);
// sayHello("hello");
}
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Timer {
}
@SpringBootApplication
@RestController
public class SpringBootDemoApplication {
//这里必须使用Person接口做注入
@Autowired
private Person chinese;
@RequestMapping("/test")
public void test() {
chinese.sayHello("listen");
System.out.println(chinese.getClass());
}
public static void main(String[] args) {
SpringApplication.run(SpringBootDemoApplication.class, args);
}
}
@Aspect
@Component
public class AdviceTest {
@Pointcut("@annotation(com.haocdp.coding.spring.Timer)")
public void pointcut() {
}
@Before("pointcut()")
public void before() {
System.out.println("before");
}
@After("pointcut()")
public void after() {
System.out.println("after");
}
@AfterReturning(pointcut = "pointcut()")
public void afterReturning() {
System.out.println("after return");
}
@AfterThrowing(pointcut = "pointcut()")
public void afterThrowing() {
System.out.println("after throwing");
}
@Around("pointcut()")
public void around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("before around");
pjp.proceed();
System.out.println("after around");
}
}
执行结果:
before around
before
-- sayHello() --
after around
after
after return
1.2 异常情况:
修改Chinese代码:
@Component
public class Chinese implements Person {
@Timer
@Override
public String sayHello(String name) {
throw new IllegalArgumentException("异常");
}
@Override
public void eat(String food) {
System.out.println("我正在吃:" + food);
// sayHello("hello");
}
}
执行结果:
before around
before
抛出异常
after
after throwing
新加Aspect类:
@Aspect
@Component
public class AdviceTest2 {
@Pointcut("@annotation(com.haocdp.coding.spring.Timer)")
public void pointcut() {
}
@Before("pointcut()")
public void before() {
System.out.println("before-2");
}
@After("pointcut()")
public void after() {
System.out.println("after-2");
}
@AfterReturning(pointcut = "pointcut()")
public void afterReturning() {
System.out.println("after return -2");
}
@AfterThrowing(pointcut = "pointcut()")
public void afterThrowing() {
System.out.println("after throwing -2");
}
@Around("pointcut()")
public void around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("before around -2");
pjp.proceed();
System.out.println("after around -2");
}
}
执行结果:
情况1:
before around -2
before-2
before around
before
-- sayHello() --
after around
after
after return
after around -2
after-2
after return -2
情况2:
before around
before
before around -2
before-2
-- sayHello() --
after around -2
after-2
after return -2
after around
after
after return
哪个Aspect先执行是随机的,如果需要定义顺序,可以使用@Order注解修饰Aspect类。值越小,优先级越高。
@Order(1)
@Aspect
@Component
public class AdviceTest2 {
@Pointcut("@annotation(com.haocdp.coding.spring.Timer)")
public void pointcut() {
}
@Before("pointcut()")
public void before() {
System.out.println("before-2");
}
@After("pointcut()")
public void after() {
System.out.println("after-2");
}
@AfterReturning(pointcut = "pointcut()")
public void afterReturning() {
System.out.println("after return -2");
}
@AfterThrowing(pointcut = "pointcut()")
public void afterThrowing() {
System.out.println("after throwing -2");
}
@Around("pointcut()")
public void around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("before around -2");
pjp.proceed();
System.out.println("after around -2");
}
}
@Order(2)
@Aspect
@Component
public class AdviceTest {
@Pointcut("@annotation(com.haocdp.coding.spring.Timer)")
public void pointcut() {
}
@Before("pointcut()")
public void before() {
System.out.println("before");
}
@After("pointcut()")
public void after() {
System.out.println("after");
}
@AfterReturning(pointcut = "pointcut()")
public void afterReturning() {
System.out.println("after return");
}
@AfterThrowing(pointcut = "pointcut()")
public void afterThrowing() {
System.out.println("after throwing");
}
@Around("pointcut()")
public void around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("before around");
pjp.proceed();
System.out.println("after around");
}
}
这样的执行结果就一直会是:
before around -2
before-2
before around
before
-- sayHello() --
after around
after
after return
after around -2
after-2
after return -2