10、多切面运行顺序
1、再多创建一个切面类ValidateAspect:将LogUtils切面类的通知方法复制过来
package com.fxp.util;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import java.util.Arrays;
@Aspect
@Component
public class ValidateAspect {
@Before("com.fxp.util.LogUtils.method()")
public void logStart(JoinPoint joinPoint){
//拿到目标方法的参数
Object[] args = joinPoint.getArgs();
//拿到目标方法的方法签名
Signature signature = joinPoint.getSignature();
//获取方法名
String name = signature.getName();
System.out.println("ValidateAspect....["+name+"]开始执行.....它的参数是:"+ Arrays.asList(args)+"");
}
@AfterReturning(value="com.fxp.util.LogUtils.method()",returning = "result")
public void LogReturn(JoinPoint joinPoint,Object result){
Signature signature = joinPoint.getSignature();
String name = signature.getName();
System.out.println("ValidateAspect....["+name+"]正常执行完毕.....,结果是:"+result+"");
}
@AfterThrowing(value="com.fxp.util.LogUtils.method()",throwing = "e")
public void LogErr(JoinPoint joinPoint,Exception e) {
Signature signature = joinPoint.getSignature();
String name = signature.getName();
//拿到异常信息
System.out.println("ValidateAspect....["+name+"]出现异常:"+e+"");
}
@After("com.fxp.util.LogUtils.method()")
public void LogEnd(JoinPoint joinPoint) {
System.out.println("ValidateAspect....["+joinPoint.getSignature().getName()+"]方法最终执行完毕");
}
}
切入点表达式还有一种方法,就是:
@Before("com.fxp.util.LogUtils.method()")
可以直接从LogUtils类中,抽取可重用的那个方法,直接调用过来。
2、为了便于观察,先将LogUtils中的环绕通知关掉,查看运行结果:
可以看到:LogUtils前置、VaAspect前置、VaAspect后置、VaAspect返回、LogUtils后置、LogUtils返回。
3、原因:
4、为什么是LogUtils在前呢,很简单,它是根据切面类的类名的首字母来判断先后的。
5、加上环绕通知,三个通知一起运行
运行结果:
因为环绕通知是优先执行的,所以这里先执行环绕通知的前置,然后执行LogUtils的前置,然后执行VaAspect的前置,接下去为什么是执行VaAspect的后置和返回通知呢,这里明确一点,我们设置的环绕通知是在LogUtils里面的,所以它会一步步往外执行,当执行到VaAspect的前置通知的时候,接下去会先把VaAspect的后置和返回通知执行完毕,然后才到LogUtils,但是在LogUtils里面有个环绕通知,环绕通知优先执行,所以先执行环绕通知的后置和返回通知,最后再执行LogUtils的后置和返回通知。
总结:环绕通知只在Log切面有效,跟Va切面没有关系。
6、补充
如果想改变切面的执行顺序,也可以通过@Order注解来改变,1代表最高优先级。哪个切面想先执行,就在哪个切面类上添加@Order(1)。