随笔 - 1162  文章 - 0  评论 - 16  阅读 - 59万 

一、通知概述

        (1)在具体的连接点上要执行的操作;
        (2)一个切面可以包括一个或者多个通知;
        (3)通知所使用的注解的值往往是切入点表达式;

 

二、前置通知

  (1)前置通知:在方法执行之前执行的通知;
  (2)使用 @Before 注解
复制代码
    /**
      * @Before:将方法指定为前置通知
      * 必须设置 value,其值为 切入点表达式
      * 前置通知:作用于方法执行之前
      */
     @Before(value = "execution(public int  com.spring.aop.ICalc.add(int, int))")
     public void beforeMethod(JoinPoint joinPoint) {
         System.out.println("方法执行之前");
         Object[] args = joinPoint.getArgs();   //获取方法的参数
         String methodName =  joinPoint.getSignature().getName();  //获取方法名
         System.out.println("方法名:" + methodName +  ",参数:" + Arrays.toString(args));
     }
复制代码

 

 

三、后置通知

  (1)后置通知:后置通知是在连接点完成之后执行的,即连接点返回结果或者抛出异常的时候;
  (2)使用 @After 注解;
复制代码
    /**
      * @After:将方法标注为后置通知
      * 后置通知:作用于方法的 finally 语句块中,即不管有没有异常都会执行
      * @param joinPoint
      */
     @After(value = "execution(public int  com.spring.aop.ICalc.*(int, int))")
     public void afterMethod(JoinPoint joinPoint) {
         System.out.println("方法执行之后");
         Object[] args = joinPoint.getArgs();   //获取方法的参数
         String methodName =  joinPoint.getSignature().getName();  //获取方法名
         System.out.println("方法名:" + methodName +  ",参数:" + Arrays.toString(args));
     }
复制代码

 

 

四、返回通知

  (1)返回通知:无论连接点是正常返回还是抛出异常,后置通知都会执行。如果只想在连接点返回的时候记录日志,应使用返回通知代替后置通知;
  (2)使用 @AfterReturning 注解,在返回通知中访问连接点的返回值;
    ① 在返回通知中,只要将 returning 属性添加到 @AfterReturning 注解中,就可以访问连接点的返回值,该属性的值即为用来传入返回值的参数名称;
      returning属性:告诉Spring使用什么变量来接结果返回值
     ② 必须在通知方法的签名中添加一个同名参数,在运行时 Spring AOP 会通过这个参数传递返回值;
     ③ 原始的切点表达式需要出现在 pointcut 属性中;
复制代码
    /**
      * @AfterReturning:将方法标注为返回通知;
      * 返回通知:作用于方法执行之后,如果发生了异常,就不再执行
      * 可通过 returning 设置接收方法返回值的变量名
      * 要想在方法中使用,必须在方法的形参中设置和变量名相同的参数名的参数
      * @param joinPoint
      * @param result
      */
     @AfterReturning(value = "execution(public int  com.spring.aop.ICalc.*(int, int))", returning="result")
     public void afterReturningMethod(JoinPoint  joinPoint, Object result) {
         System.out.println("方法返回通知");
         Object[] args = joinPoint.getArgs();                      //获取方法的参数
         String methodName =  joinPoint.getSignature().getName();  //获取方法名
         System.out.println("方法名:" + methodName +  ",参数:" + Arrays.toString(args));
         System.out.println("返回值:"+result);
     }
复制代码

 

 

五、异常通知

  (1)异常通知:只在连接点抛出异常时才执行异常通知;        
  (2)将 throwing 属性添加到 @AfterThrowing 注解中,也可以访问连接点抛出的异常。
      throwing:告诉Spring使用什么变量来接结果异常信息
                 Throwable 是所有错误和异常类的顶级父类,所以在异常通知方法可以捕获到任何错误和异常。
        (3)如果只对某种特殊的异常类型感兴趣,可以将参数声明为其他异常的参数类型,然后通知就只在抛出这个类型及其子类的异常时才被执行;
复制代码
    /**
      * @AfterThrowing:将方法标注为异常通知(例外通知)
      * 异常通知(例外通知):作用于方法抛出异常时
      * 可通过throwing设置接收方法返回的异常信息
      * 在参数列表中可通过具体的异常类型,来对指定的异常信息进行操作
      * @param ex
      */
     @AfterThrowing(value = "execution(public int  com.spring.aop.ICalc.*(int, int))",throwing="ex")
     public void afterThrowingMethod(Exception ex) {
         System.out.println("有异常了。");
         System.out.println("message:" + ex);
     }
     public void  afterThrowingMethod(ArithmeticException ex) {        //可以指定异常的类型,根据不同类型的异常,选择不同的操作
         System.out.println("有异常了。");
         System.out.println("message:" + ex);
     }
复制代码

 

 

六、Spring对通知方法的约束

  Spring对通知方法的要求不严格:修改返回值和去掉静态static都照样运行

  但唯一有要求的是方法的参数列表一定不能乱写 原因:通知方法是Spring利用反射调用的,每次调用方法都需要确定这个方法的参数表的值; 参数表上的每一个参数,Spring都得知道是什么。

  举例:

复制代码
    @After("execution(public int com.achang.inter.impl.MyMathCalculator.*(int,int))")
    public  int logEnd(JoinPoint joinPoint){
        String name = joinPoint.getSignature().getName();
        System.out.println("【" + name + "】方法执行最终完成");
        return 0;
    }
复制代码

 

  对于有异常和返回值的方法,指定的异常、结果返回值一定要写大:

1
2
3
4
public static void logException(JoinPoint joinPoint,Exception e,Object result){
 }
 
//Exception e, Object result

  

  不然他只接收,你写的异常和返回值类型如:只接受空指针异常和Integer类型

1
2
NullPointerException e
Integer result

  

 

七、通知方法的执行顺序

  通知方法的执行顺序:

1
2
3
正常执行情况:@Before(前置通知)—>@After(后置通知)—>@AfterReturning(正常返回)
 
异常执行情况:@Before(前置通知)—>@After(后置通知)—>@AfterThrowing(方法异常)

  

 

posted on   格物致知_Tony  阅读(73)  评论(0编辑  收藏  举报
编辑推荐:
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· 面试官:你是如何进行SQL调优的?
点击右上角即可分享
微信分享提示

目录导航