一.通知有哪几种?
1.Around:环绕通知,在方法执行之前和之后调用的通知
2.before:前置通知,在方法执行前调用
3.after:后置通知,在方法执行之后调用的通知
4.afterReturning:方法成功完成或有异常被其他切面catch后调用的通知
5.afterThrowing:当方法抛出异常退出时执行的通知
二.通知的执行顺序是怎么样的?
在一个切面类里面,定义了五种类型的通知,五种通知的切点相同,那么这几种类型的通知的执行顺序是什么样的呢?
说实话,如果不写个切面实际运行,还真难下结论。
@Component
@Aspect
public class LogAspect {
//切点
@Pointcut("execution(public * com.netty.use.nettyuse.controller.*.*(..))")
public void webLog(){}
@Around(value = "webLog()")
public Object around(ProceedingJoinPoint pjp) {
try {
System.out.println("Around:方法环绕开始.....");
Object o = pjp.proceed();
System.out.println("Around:方法环绕结束,结果是 :" + o);
return o;
} catch (Throwable e) {
System.out.println(pjp.getSignature() + " 出现异常: "+e.getMessage());
return "";
}
}
@Before(value = "webLog()")
public void before(JoinPoint pjp) {
try {
System.out.println("before方法执行.....");
} catch (Throwable e) {
System.out.println(pjp.getSignature() + " 出现异常: "+e.getMessage());
}
}
@After(value = "webLog()")
public void after(JoinPoint pjp) {
System.out.println("after方法执行.....");
}
@AfterReturning(value = "webLog()")
public void afterReturning(JoinPoint pjp) {
System.out.println("afterReturning方法执行.....");
}
@AfterThrowing(value = "webLog()")
public void afterThrowing(JoinPoint pjp) {
System.out.println("afterThrowing方法执行.....");
}
}
方法正常情况的结果输出如下:
Around:方法环绕开始.....
before方法执行.....
familyDTO:{}
Around:方法环绕结束,结果是 :
after方法执行.....
afterReturning方法执行.....
通知的执行的顺序如下:
around->before->方法本身->around->after->afterReturning
如果执行的过程中出现了异常,那么输出如下:
Around:方法环绕开始.....
before方法执行.....
familyDTO:{"count":1}
String
com.netty.use.nettyuse.controller.LaController.methodForObjectParam(FamilyDTO) 出现异常: / by zero
after方法执行.....
afterReturning方法执行.....
异常被around通知catch住,afterReturning通知也执行了。
我们去掉around通知,输出如下:
before方法执行.....
familyDTO:{"count":1}
after方法执行.....
afterThrowing方法执行.....
afterThrowing通知在after通知之后执行。
三.通知排序源码:
ReflectiveAspectJAdvisorFactory类的静态代码块中,定义一个比较器:
private static final Comparator<Method> METHOD_COMPARATOR;
static {
Comparator<Method> adviceKindComparator = new ConvertingComparator<>(
new InstanceComparator<>(
Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class),
(Converter<Method, Annotation>) method -> {
AspectJAnnotation<?> annotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
return (annotation != null ? annotation.getAnnotation() : null);
});
Comparator<Method> methodNameComparator = new ConvertingComparator<>(Method::getName);
METHOD_COMPARATOR = adviceKindComparator.thenComparing(methodNameComparator);
}
\