一、前置通知
--前置通知:在方法执行之前执行的通知
--前置通知使用 @Before 注解, 并将切入点表达式的值作为注解值。
/**
* 声明该方法是一个前置通知:在目标方法开始之前执行
*/
@Before("execution(public int aop.AtithmeticCalculatorImpl.*(int,int))")
public void beforeMethod(JoinPoint joinPoint){
System.out.println("调用"+joinPoint.getSignature().getName()+"方法,处理"+ Arrays.asList(joinPoint.getArgs()));
}
* 声明该方法是一个前置通知:在目标方法开始之前执行
*/
@Before("execution(public int aop.AtithmeticCalculatorImpl.*(int,int))")
public void beforeMethod(JoinPoint joinPoint){
System.out.println("调用"+joinPoint.getSignature().getName()+"方法,处理"+ Arrays.asList(joinPoint.getArgs()));
}
二、后置通知
-- 后置通知是在连接点完成之后执行的, 即连接点返回结果或者抛出异常的时候, 下面的后置通知记录了方法的终止
/**
* 在目标方法执行后(无论是否发生异常),执行的通知
* 在后置通知中无法访问目标执行的结果
*/
@After("execution(public int aop.AtithmeticCalculatorImpl.*(int,int))")
public void afterMethod(JoinPoint joinPoint){
System.out.println("调用"+joinPoint.getSignature().getName()+"方法结束");
}
* 在目标方法执行后(无论是否发生异常),执行的通知
* 在后置通知中无法访问目标执行的结果
*/
@After("execution(public int aop.AtithmeticCalculatorImpl.*(int,int))")
public void afterMethod(JoinPoint joinPoint){
System.out.println("调用"+joinPoint.getSignature().getName()+"方法结束");
}
三、返回通知
--在返回通知中, 只要将 returning属性添加到 @AfterReturning注解中, 就可以访问连接点的返回值. 该属性的值即为用来传入返回值的参数名称.
--必须在通知方法的签名中添加一个同名参数. 在运行时, Spring AOP 会通过这个参数传递返回值.
--原始的切点表达式需要出现在 pointcut 属性中
/**
* 在方法正常结束的时候执行
* 返回通知可以获取目标方法的返回值
*/
* 在方法正常结束的时候执行
* 返回通知可以获取目标方法的返回值
*/
@AfterReturning(value = "execution(public int aop.AtithmeticCalculatorImpl.*(int,int))", returning = "result")
public void afterReturningMethod(JoinPoint joinPoint,Override result){
System.out.println("处理结果为:"+result.toString());
}
public void afterReturningMethod(JoinPoint joinPoint,Override result){
System.out.println("处理结果为:"+result.toString());
}
四、异常通知
--只在连接点抛出异常时才执行异常通知
--将 throwing 属性添加到 @AfterThrowing 注解中, 也可以访问连接点抛出的异常. Throwable是所有错误和异常类的超类. 所以在异常通知方法可以捕获到任何错误和异常.
--如果只对某种特殊的异常类型感兴趣, 可以将参数声明为其他异常的参数类型. 然后通知就只在抛出这个类型及其子类的异常时才被执行.
/**
* 在目标方法出现异常时执行
* 可以访问到方法的异常对象,且可以指定在出现特定异常时在执行通知代码
*/
@AfterThrowing(value = "execution(public int aop.AtithmeticCalculatorImpl.*(int,int))",throwing = "e")
public void afterThrowingMethod(JoinPoint joinPoint,Exception e){
System.out.println(joinPoint.getSignature().getName()+"发生异常:"+e);
}
* 在目标方法出现异常时执行
* 可以访问到方法的异常对象,且可以指定在出现特定异常时在执行通知代码
*/
@AfterThrowing(value = "execution(public int aop.AtithmeticCalculatorImpl.*(int,int))",throwing = "e")
public void afterThrowingMethod(JoinPoint joinPoint,Exception e){
System.out.println(joinPoint.getSignature().getName()+"发生异常:"+e);
}
五、环绕通知
--环绕通知是所有通知类型中功能最为强大的, 能够全面地控制连接点. 甚至可以控制是否执行连接点.
--对于环绕通知来说, 连接点的参数类型必须是 ProceedingJoinPoint. 它是 JoinPoint的子接口, 允许控制何时执行, 是否执行连接点.
--在环绕通知中需要明确调用 ProceedingJoinPoint 的 proceed() 方法来执行被代理的方法. 如果忘记这样做就会导致通知被执行了, 但目标方法没有被执行.
--注意: 环绕通知的方法需要返回目标方法执行之后的结果, 即调用 joinPoint.proceed(); 的返回值, 否则会出现空指针异常
/**
* 环绕方法需要携带ProceedingJoinPoint类型的参数
* 环绕通知类似于动态代理的过程,ProceedingJoinPoint类型的参数可以决定是否执行目标方法
* 且环绕通知必须有返回值,返回值为目标方法的返回值
*/
@Around("execution(public int aop.AtithmeticCalculatorImpl.*(int,int))")
public Object aroundMethod(ProceedingJoinPoint pjp){
Object obj=null;
try {
//前置通知
System.out.println("调用"+pjp.getSignature().getName()+"方法,处理"+ Arrays.asList(pjp.getArgs()));
//执行方法
obj=pjp.proceed();
//返回通知
System.out.println("处理结果为:"+obj);
} catch (Throwable e) {
//异常通知
System.out.println(pjp.getSignature().getName()+"发生异常:"+e);
//抛出异常
throw new RuntimeException(e);
}
//后置通知
System.out.println("调用"+pjp.getSignature().getName()+"方法结束");
return obj;
}
* 环绕方法需要携带ProceedingJoinPoint类型的参数
* 环绕通知类似于动态代理的过程,ProceedingJoinPoint类型的参数可以决定是否执行目标方法
* 且环绕通知必须有返回值,返回值为目标方法的返回值
*/
@Around("execution(public int aop.AtithmeticCalculatorImpl.*(int,int))")
public Object aroundMethod(ProceedingJoinPoint pjp){
Object obj=null;
try {
//前置通知
System.out.println("调用"+pjp.getSignature().getName()+"方法,处理"+ Arrays.asList(pjp.getArgs()));
//执行方法
obj=pjp.proceed();
//返回通知
System.out.println("处理结果为:"+obj);
} catch (Throwable e) {
//异常通知
System.out.println(pjp.getSignature().getName()+"发生异常:"+e);
//抛出异常
throw new RuntimeException(e);
}
//后置通知
System.out.println("调用"+pjp.getSignature().getName()+"方法结束");
return obj;
}