Spring通知(前置通知,后置通知,返回通知,异常通知,环绕通知)

一、前置通知
--前置通知 : 在方法执行之前执行的通知
--前置通知使用 @Before 注解 , 并将切入点表达式的值作为注解值。
/**
 * 声明该方法是一个前置通知:在目标方法开始之前执行
 */
@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 () + "方法结束" ) ;
}

三、返回通知
--在返回通知中, 只要将 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 ()) ;
}

四、异常通知
--只在连接点抛出异常时才执行异常通知
--将 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 ) ;
}

五、环绕通知
--环绕通知是所有通知类型中功能最为强大的, 能够全面地控制连接点. 甚至可以控制是否执行连接点.
--对于环绕通知来说, 连接点的参数类型必须是 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 ;
}

猜你喜欢

转载自blog.csdn.net/qq_34886352/article/details/79321758