• (III)AOP:第七节:环绕通知


    一、环绕通知

            (1)环绕通知是所有通知类型中功能最为强大的,能够全面地控制连接点,甚至可以控制是否执行连接点;
            (2)对于环绕通知来说,连接点的参数类型必须是 ProceedingJoinPoint。它是 JoinPoint 的子接口,允许控制何时执行,是否执行连接点;
            (3)在环绕通知中需要明确调用 ProceedingJoinPoint 的 proceed() 方法来执行被代理的方法。如果忘记这样做就会导致通知被执行了,但目标方法没有被执行;
            (4)注意:环绕通知的方法需要返回目标方法执行之后的结果,即调用 joinPoint.proceed() 的返回值,否则会出现空指针异常;
     
       环绕通知:
        /**
         * @Around:环绕:是Spring 中强大的通知,本质就是动态代理
         * 
         * try{
         *      //前置通知
         *      method.invoke(obj,args);
         *      //返回通知
         * }catch(e){
         *      //异常通知
         * }finally{
         *     //后置通知
         * }
         *
         * 四合一通知就是环绕通知
         * 环绕通知中有一个参数:ProceedingJoinPoint pjp
         */
        @Around("myPoint()")
        public Object myAround(ProceedingJoinPoint pjp) throws Throwable {
    
            String methodName = pjp.getSignature().getName();
            Object[] args = pjp.getArgs();
            Object proceed = null;
            try {
                //@Before
                System.out.println("【环绕前置通知】---"+ methodName +"---【方法开始】");
                //就是利用反射调用目标方法即可,就是 method.invoke(obj, args)
                proceed = pjp.proceed(args);
                //@AfterReturning
                System.out.println("【环绕返回通知】---"+ methodName +"---【方法返回,返回值 "+ proceed +"】");
            } catch (Exception e) {
                //@AfterThrowing
                System.out.println("【环绕异常通知】---"+ methodName +"---【方法出现异常】,异常信息:" + e);
            } finally {
                //@After
                System.out.println("【环绕后置通知】---"+ methodName +"---【方法结束】");
            }
    
    
            //反射调用后的返回值也一定返回出去,不返回会空指针
            return proceed;
        }
     
     

    二、环绕通知顺序&抛出异常让其他通知感受到

      当同时使用了环绕通知和普通通知,再来看一下执行顺序:

         /*
         * 环绕通知:是优先于普通通知执行,执行顺序:
         *
         *  普通通知:
         *  [普通前置]
         *  目标方法执行
         *  [普通后置]
         *  [普通方法返回/方法异常]
         *
         *
         *  普通通知+环绕通知
         *
         * 【普通前置】
         *
         *  {
         *  try{
         *      环绕前置
         *      环绕执行目标方法:目标方法执行
         *      环绕返回
         *  }catch(){
         *      环绕异常
         *  }finally
         *      环绕后置
         *      }
         *  }
         *  【普通后置】
         *  【普通方法返回/方法异常】
         *
         *
         *
         *  新的顺序:
         *      环绕前置 --- 普通前置 --- 目标方法执行 --- 环绕返回/异常 --- 环绕后置 --- 普通返回/异常 --- 普通后置
         *
         *
         *  注意:环绕通知的异常一定要抛出去
         *
         */
        @Around("myPoint()")
        public Object myAround(ProceedingJoinPoint pjp) throws Throwable {
    
            String methodName = pjp.getSignature().getName();
            Object[] args = pjp.getArgs();
            Object proceed = null;
            try {
                //@Before
                System.out.println("【环绕前置通知】---"+ methodName +"---【方法开始】");
                //就是利用反射调用目标方法即可,就是 method.invoke(obj, args)
                proceed = pjp.proceed(args);
                //@AfterReturning
                System.out.println("【环绕返回通知】---"+ methodName +"---【方法返回,返回值 "+ proceed +"】");
            } catch (Exception e) {
                //@AfterThrowing
                System.out.println("【环绕异常通知】---"+ methodName +"---【方法出现异常】,异常信息:" + e);
                //为了让外界能知道这个异常,这个异常一定要抛出去
                throw new RuntimeException(e);
            } finally {
                //@After
                System.out.println("【环绕后置通知】---"+ methodName +"---【方法结束】");
            }
    
    
            //反射调用后的返回值也一定返回出去,不返回会空指针
            return proceed;
        }

      执行顺序:

      

      注意:环绕通知里面的异常一定要抛出去。

     

  • 相关阅读:
    为蓝桥杯准备
    Java里子类调用父类构造方法问题
    boost库的Singleton的实现以及static成员的初始化问题
    VS2005调试小记
    <转载>程序员每天该做的事
    vs2005, 2008 使用了未初始化的msg变量
    转载 vs2005 快捷键大全
    VS2005右键点击转到定义后出现“未定义符号”的提示及其解决
    软件工程配置规范(VC2005) 第二版(转载)
    匆忙赶路的时候别忘了适时停下来回头看看
  • 原文地址:https://www.cnblogs.com/niujifei/p/15450502.html
Copyright © 2020-2023  润新知