一.前置通知,环绕通知,后置通知,异常通知,最终通知
①前置通知
在目标方法执行之前执行的通知,前置通知方法可以没有参数,也可以额外接受一个JoinPoint,Spring会将该对象自动传入,代表当前的连接点,通过该对象可以获取目标对象和目标方法的相关信息;若接收JoinPoint,必须保证其为方法的第一个参数,否则报错。
<aop:before method ="before" pointcut-ref="pc01"/>
@Component
public class First{
public void before(){
System.out.println("before...");
}
}
//前置通知
public void before(JoinPoint jp){
//目标对象
Object target = jp.getTarget();
Class clz = target.getClass();
//目标方法
MethodSignature signature = (MethodSignature) jp.getSignature();
Method method = signature.getMethod();
System.out.println("before"+clz+".."+method);
}
②环绕通知
在目标方法执行之前和之后都可以执行额外代码的通知,在环绕通知中必须显示的调用目标方法,否则目标方法不会执行;这个显示调用是通过ProceedingJoinPoint来实现的可以在环绕通知中接受一个此类型的形参,spring容器会自动将该对象传入,这个参数必须处在环绕通知的第一个形参位置。环绕通知需要返回返回值,否则真正调用者将拿不到返回值,只能得到一个null。
环绕通知的功能:
a.控制目标方法是否执行
b.目标方法执行之前或之后执行额外代码
c.控制是否返回返回值
d.改变返回值
虽然有很多功能,但是不能滥用,否则会破坏软件分层的高内聚,低耦合的原则。
<aop:around method ="around" pointcut-ref="pc01"/>
public Object around(ProceedingJoinPoint jp) throws Throwable{
System.out.print("around before..");
Object obj = jp.proceed();//显式调用目标方法
System.out.print("around after..");
return obj;
}
③后置通知
在目标方法成功执行后执行的通知(具体实现代码同前置通知)
<aop:after-returning method ="afterReturn" pointcut-ref="pc01"/>
④异常通知
在目标方法抛出异常时执行的通知
<aop:after-throwing method ="afterThrow" pointcut-ref="pc01" throwing="e"/>
public void atferThrow(JointPoint jp,Throwable e){
Class clz = jp.getTarget().getClass();
String name = jp.getSignature().getName();
System.out.println("afterThrow.."+["+clz+"]..["+name+"]);
}
⑤最终通知
是在目标方法执行之后的通知,和后置通知不同之处在于,后置通知是在方法正常返回后执行的通知,若抛出异常,后置通知就不会执行,最终通知不管目标方法正常还是一场都会执行,后置通知可以通过配置得到返回值,而最终通知无法得到。
<aop:after method ="after" pointcut-ref="pc01">
public void after(){
System.out.println("after..");
}
二.五种通知的常见使用场景、
前置通知(记录日志),方法将被调用
环绕通知(控制事务,权限控制)
后置通知(记录日志,方法已经成功调用)
异常通知(异常处理,控制事务)
最终通知(记录日志,方法已调用,但不一定成功)