Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 6328|回复: 0

Spring AOP--返回通知,异常通知和环绕通知

[复制链接]
  • TA的每日心情
    奋斗
    2024-4-6 11:05
  • 签到天数: 748 天

    [LV.9]以坛为家II

    2034

    主题

    2092

    帖子

    70万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    705612
    发表于 2021-4-5 14:55:31 | 显示全部楼层 |阅读模式

    在上篇文章中学习了Spring AOP,并学习了前置通知和后置通知。地址为:http://www.cnblogs.com/dreamfree/p/4095858.html

    在本文中,将继续上篇的学习,继续了解返回通知、异常通知和环绕通知。具体的含义详见代码注释

     1 package com.yl.spring.aop;
     2 
     3 import java.util.Arrays;
     4 
     5 import org.aspectj.lang.JoinPoint;
     6 import org.aspectj.lang.ProceedingJoinPoint;
     7 import org.aspectj.lang.annotation.After;
     8 import org.aspectj.lang.annotation.AfterReturning;
     9 import org.aspectj.lang.annotation.AfterThrowing;
    10 import org.aspectj.lang.annotation.Around;
    11 import org.aspectj.lang.annotation.Aspect;
    12 import org.aspectj.lang.annotation.Before;
    13 import org.springframework.stereotype.Component;
    14 
    15 @Component
    16 @Aspect
    17 public class LoggingAspect {
    18     
    19     /**
    20      * 在com.yl.spring.aop.ArithmeticCalculator接口的每一个实现类的每一个方法开始之前执行一段代码
    21      */
    22     @Before("execution(public int com.yl.spring.aop.ArithmeticCalculator.*(..))")
    23     public void beforeMethod(JoinPoint joinPoint) {
    24         String methodName = joinPoint.getSignature().getName();
    25         Object[] args = joinPoint.getArgs();
    26         System.out.println("The method " + methodName + " begins with " + Arrays.asList(args));
    27     }
    28     
    29     /**
    30      * 在com.yl.spring.aop.ArithmeticCalculator接口的每一个实现类的每一个方法执行之后执行一段代码
    31      * 无论该方法是否出现异常
    32      */
    33     @After("execution(public int com.yl.spring.aop.ArithmeticCalculator.*(..))")
    34     public void afterMethod(JoinPoint joinPoint) {
    35         String methodName = joinPoint.getSignature().getName();
    36         Object[] args = joinPoint.getArgs();
    37         System.out.println("The method " + methodName + " ends with " + Arrays.asList(args));
    38     }
    39     
    40     /**
    41      * 方法正常结束后执行的代码
    42      * 返回通知是可以访问到方法的返回值的
    43      */
    44     @AfterReturning(value="execution(public int com.yl.spring.aop.ArithmeticCalculator.*(..))", returning="result")
    45     public void afterReturning(JoinPoint joinPoint, Object result) {
    46         String methodName = joinPoint.getSignature().getName();
    47         System.out.println("The method " + methodName + " return with " + result);
    48     }
    49     
    50     /**
    51      * 在方法出现异常时会执行的代码
    52      * 可以访问到异常对象,可以指定在出现特定异常时在执行通知代码
    53      */
    54     @AfterThrowing(value="execution(public int com.yl.spring.aop.ArithmeticCalculator.*(..))", throwing="ex")
    55     public void afterThrowing(JoinPoint joinPoint, Exception ex) {
    56         String methodName = joinPoint.getSignature().getName();
    57         System.out.println("The method " + methodName + " occurs exception: " + ex);
    58     }
    59     
    60     /**
    61      * 环绕通知需要携带ProceedingJoinPoint类型的参数
    62      * 环绕通知类似于动态代理的全过程:ProceedingJoinPoint类型的参数可以决定是否执行目标方法。
    63      * 而且环绕通知必须有返回值,返回值即为目标方法的返回值
    64      */
    65     @Around("execution(public int com.yl.spring.aop.ArithmeticCalculator.*(..))")
    66     public Object aroundMethod(ProceedingJoinPoint pjd) {
    67         Object result = null;
    68         String methodName = pjd.getSignature().getName();
    69         //执行目标方法
    70         try {
    71             //前置通知
    72             System.out.println("The method " + methodName + " begins with " + Arrays.asList(pjd.getArgs()));
    73             result = pjd.proceed();
    74             //返回通知
    75             System.out.println("The method " + methodName + " ends with " + Arrays.asList(pjd.getArgs()));
    76         } catch (Throwable e) {
    77             //异常通知
    78             System.out.println("The method " + methodName + " occurs expection : " + e);
    79             throw new RuntimeException(e);
    80         }
    81         //后置通知
    82         System.out.println("The method " + methodName + " ends");
    83         return result;
    84     }
    85     
    86 }

     

    切面的优先级  

      为项目增加一个新的切面类,负责验证功能,则需要指定切面执行的顺序。即切面的优先级。具体方法是给切面类增加@Order注解,并指定具体的数字,值越小优先级越高

     1 package com.yl.spring.aop;
     2 
     3 import java.util.Arrays;
     4 
     5 import org.aspectj.lang.JoinPoint;
     6 import org.aspectj.lang.annotation.Aspect;
     7 import org.aspectj.lang.annotation.Before;
     8 import org.springframework.core.annotation.Order;
     9 import org.springframework.stereotype.Component;
    10 
    11 /**
    12  * 可以使用@Order注解指定切面的优先级,值越小优先级越高
    13  * @author yul
    14  *
    15  */
    16 @Order(2)
    17 @Component
    18 @Aspect
    19 public class ValidationAspect {
    20     
    21     @Before("execution(public int com.yl.spring.aop.ArithmeticCalculator.*(..))")
    22     public void vlidateArgs(JoinPoint joinPoint) {
    23         System.out.println("validate: " + Arrays.asList(joinPoint.getArgs()));
    24     }
    25 }

     切点表达式的重用:

      在LoggingAspect类中,切点的表达式可以先定义,在使用。

     1 package com.yl.spring.aop;
     2 
     3 import java.util.Arrays;
     4 
     5 import org.aspectj.lang.JoinPoint;
     6 import org.aspectj.lang.ProceedingJoinPoint;
     7 import org.aspectj.lang.annotation.After;
     8 import org.aspectj.lang.annotation.AfterReturning;
     9 import org.aspectj.lang.annotation.AfterThrowing;
    10 import org.aspectj.lang.annotation.Around;
    11 import org.aspectj.lang.annotation.Aspect;
    12 import org.aspectj.lang.annotation.Before;
    13 import org.aspectj.lang.annotation.Pointcut;
    14 import org.springframework.core.annotation.Order;
    15 import org.springframework.stereotype.Component;
    16 @Order(1)
    17 @Component
    18 @Aspect
    19 public class LoggingAspect {
    20     
    21     /**
    22      * 定义一个方法,用于声明切入点表达式。一般的,该方法中再不需要添加其他的代码
    23      * 使用@Pointcut 来声明切入点表达式
    24      * 后面的其他通知直接使用方法名直接引用方法名即可
    25      */
    26     @Pointcut("execution(public int com.yl.spring.aop.ArithmeticCalculator.*(..))")
    27     public void declareJoinPointExpression() {
    28         
    29     }
    30     
    31     /**
    32      * 在com.yl.spring.aop.ArithmeticCalculator接口的每一个实现类的每一个方法开始之前执行一段代码
    33      */
    34     @Before("declareJoinPointExpression()")
    35     public void beforeMethod(JoinPoint joinPoint) {
    36         String methodName = joinPoint.getSignature().getName();
    37         Object[] args = joinPoint.getArgs();
    38         System.out.println("The method " + methodName + " begins with " + Arrays.asList(args));
    39     }
    40     
    41     /**
    42      * 在com.yl.spring.aop.ArithmeticCalculator接口的每一个实现类的每一个方法执行之后执行一段代码
    43      * 无论该方法是否出现异常
    44      */
    45     @After("declareJoinPointExpression()")
    46     public void afterMethod(JoinPoint joinPoint) {
    47         String methodName = joinPoint.getSignature().getName();
    48         Object[] args = joinPoint.getArgs();
    49         System.out.println("The method " + methodName + " ends with " + Arrays.asList(args));
    50     }
    51     
    52     /**
    53      * 方法正常结束后执行的代码
    54      * 返回通知是可以访问到方法的返回值的
    55      */
    56     @AfterReturning(value="declareJoinPointExpression()", returning="result")
    57     public void afterReturning(JoinPoint joinPoint, Object result) {
    58         String methodName = joinPoint.getSignature().getName();
    59         System.out.println("The method " + methodName + " return with " + result);
    60     }
    61     
    62     /**
    63      * 在方法出现异常时会执行的代码
    64      * 可以访问到异常对象,可以指定在出现特定异常时在执行通知代码
    65      */
    66     @AfterThrowing(value="declareJoinPointExpression()", throwing="ex")
    67     public void afterThrowing(JoinPoint joinPoint, Exception ex) {
    68         String methodName = joinPoint.getSignature().getName();
    69         System.out.println("The method " + methodName + " occurs exception: " + ex);
    70     }
    71     
    72     /**
    73      * 环绕通知需要携带ProceedingJoinPoint类型的参数
    74      * 环绕通知类似于动态代理的全过程:ProceedingJoinPoint类型的参数可以决定是否执行目标方法。
    75      * 而且环绕通知必须有返回值,返回值即为目标方法的返回值
    76      */
    77     @Around("declareJoinPointExpression()")
    78     public Object aroundMethod(ProceedingJoinPoint pjd) {
    79         Object result = null;
    80         String methodName = pjd.getSignature().getName();
    81         //执行目标方法
    82         try {
    83             //前置通知
    84             System.out.println("The method " + methodName + " begins with " + Arrays.asList(pjd.getArgs()));
    85             result = pjd.proceed();
    86             //返回通知
    87             System.out.println("The method " + methodName + " ends with " + Arrays.asList(pjd.getArgs()));
    88         } catch (Throwable e) {
    89             //异常通知
    90             System.out.println("The method " + methodName + " occurs expection : " + e);
    91             throw new RuntimeException(e);
    92         }
    93         //后置通知
    94         System.out.println("The method " + methodName + " ends");
    95         return result;
    96     }
    97     
    98 }

    当处于不同的类,甚至不同的包时,可以使用包名.类名.方法名    

    具体代码如下:

     1 package com.yl.spring.aop;
     2 
     3 import java.util.Arrays;
     4 
     5 import org.aspectj.lang.JoinPoint;
     6 import org.aspectj.lang.annotation.Aspect;
     7 import org.aspectj.lang.annotation.Before;
     8 import org.springframework.core.annotation.Order;
     9 import org.springframework.stereotype.Component;
    10 
    11 /**
    12  * 可以使用@Order注解指定切面的优先级,值越小优先级越高
    13  * @author yul
    14  *
    15  */
    16 @Order(2)
    17 @Component
    18 @Aspect
    19 public class ValidationAspect {
    20     
    21     @Before("com.yl.spring.aop.LoggingAspect.declareJoinPointExpression()")
    22     public void vlidateArgs(JoinPoint joinPoint) {
    23         System.out.println("validate: " + Arrays.asList(joinPoint.getArgs()));
    24     }
    25 }

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-5-17 15:35 , Processed in 0.067359 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表