AOP通知中获取数据

news2025/7/8 3:47:13

AOP通知中获取数据

之前我们写AOP仅仅是在原始方法前后追加一些操作,接下来我们要说说AOP中数据相关的内容,我们将从获取参数、获取返回值和获取异常三个方面来研究切入点的相关信息。

  • 获取切入点方法的参数:所有的通知类型都可以获取参数
    • JoinPoint:适用于前置、后置、返回后、抛出异常后通知
    • ProceedingJoinPoint:适用于环绕通知
  • 获取切入点方法返回值:前置和抛出异常后通知是没有返回值,后置通知可有可无。
    • 返回后通知
    • 环绕通知
  • 获取切入点方法运行异常信息:前置和返回后通知不会有,后置通知可有可无。
    • 抛出异常后通知
    • 环绕通知

参数获取

非环绕通知参数获取方式:

在方法上添加JoinPoint,通过JoinPoint来获取参数

@Component
@Aspect
public class MyAdvice {
    @Pointcut("execution(* com.taro.dao.BookDao.findName(..))")
    private void pt(){}

    @Before("pt()")
    public void before(JoinPoint jp) 
        Object[] args = jp.getArgs();
        System.out.println(Arrays.toString(args));
        System.out.println("before advice ..." );
    }
	//...其他的略
}

如果运行我们会发现返回值是用一个数组呈现的,因为参数的个数是不固定的,所以使用数组更通配些。

环绕通知参数获取方式

环绕通知使用的是ProceedingJoinPoint,上一篇Spring AOP通知类型里面也见过,因为ProceedingJoinPoint是JoinPoint类的子类,所以对于ProceedingJoinPoint类中应该也会有对应的getArgs()方法。
🍊个🌰:

@Component
@Aspect
public class MyAdvice {
    @Pointcut("execution(* com.taro.dao.BookDao.findName(..))")
    private void pt(){}

    @Around("pt()")
    public Object around(ProceedingJoinPoint pjp)throws Throwable {
        Object[] args = pjp.getArgs();
        System.out.println(Arrays.toString(args));
        Object ret = pjp.proceed();
        return ret;
    }
}
  • pjp.proceed()方法是有两个构造方法,分别是:
    在这里插入图片描述
  • 调用无参数的proceed,当原始方法有参数,会在调用的过程中自动传入参数
  • 所以调用这两个方法的任意一个都可以完成功能
  • 但是当需要修改原始方法的参数时,就只能采用带有参数的方法,如下:
    @Component
    @Aspect
    public class MyAdvice {
        @Pointcut("execution(* com.itheima.dao.BookDao.findName(..))")
        private void pt(){}
    
        @Around("pt()")
        public Object around(ProceedingJoinPoint pjp) throws Throwable{
            Object[] args = pjp.getArgs();
            System.out.println(Arrays.toString(args));
            args[0] = 666;
            Object ret = pjp.proceed(args);
            return ret;
        }
    	//其他的略
    }
    ```

因为这个特性,我们就可以在环绕通知中对原始方法的参数进行拦截过滤,避免由于参数的问题导致程序无法正确运行,保证代码的健壮性。

返回值获取

对于返回值,只有返回后AfterReturing和环绕Around这两个通知类型可以获取

环绕通知获取返回值

@Component
@Aspect
public class MyAdvice {
    @Pointcut("execution(* com.taro.dao.BookDao.findName(..))")
    private void pt(){}

    @Around("pt()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable{
        Object[] args = pjp.getArgs();
        System.out.println(Arrays.toString(args));
        args[0] = 666;
        Object ret = pjp.proceed(args);
        return ret;
    }
	//其他的略
}

我们很容易在上述代码中发现,ret就是方法的返回值,我们是可以直接获取,不但可以获取,如果需要还可以进行修改。

返回后通知获取返回值

@Component
@Aspect
public class MyAdvice {
    @Pointcut("execution(* com.taro.dao.BookDao.findName(..))")
    private void pt(){}

    @AfterReturning(value = "pt()",returning = "ret")
    public void afterReturning(Object ret) {
        System.out.println("afterReturning advice ..."+ret);
    }
	//其他的略
}

注意一下下面哟:

(1)参数名的问题

(2)afterReturning方法参数类型的问题
参数类型可以写成String,但是为了能匹配更多的参数类型,建议写成Object类型
(3)afterReturning方法参数的顺序问题
在这里插入图片描述

异常获取

对于获取抛出的异常,只有抛出异常后AfterThrowing和环绕Around这两个通知类型可以获取。

环绕通知获取异常

以前我们是抛出异常,现在只需要将异常捕获,就可以获取到原始方法的异常信息了

@Component
@Aspect
public class MyAdvice {
    @Pointcut("execution(* com.itheima.dao.BookDao.findName(..))")
    private void pt(){}

    @Around("pt()")
    public Object around(ProceedingJoinPoint pjp){
        Object[] args = pjp.getArgs();
        System.out.println(Arrays.toString(args));
        args[0] = 666;
        Object ret = null;
        try{
            ret = pjp.proceed(args);
        }catch(Throwable throwable){
            t.printStackTrace();
        }
        return ret;
    }
}

在catch方法中就可以获取到异常,至于获取到异常以后该如何处理,这个就和你的业务需求有关了。

抛出异常后通知获取异常

@Component
@Aspect
public class MyAdvice {
    @Pointcut("execution(* com.itheima.dao.BookDao.findName(..))")
    private void pt(){}

    @AfterThrowing(value = "pt()",throwing = "t")
    public void afterThrowing(Throwable t) {
        System.out.println("afterThrowing advice ..."+t);
    }
}

当然我们还得让原始方法抛出异常才能看到。

@Repository
public class BookDaoImpl implements BookDao {

    public String findName(int id,String password) {
        System.out.println("id:"+id);
        if(true){
            throw new NullPointerException();
        }
        return "itcast";
    }
}

注意:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/433203.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vulhub开源漏洞靶场用Java远程访问

事件起因,被迫参加某竞赛,中途发现,全员摸鱼,遂一起摸鱼Vulhub是一个面向大众的开源漏洞靶场,无需docker知识,简单执行一条命令即可编译、运行一个完整的漏洞靶场镜像。 Installation 在Ubuntu 20.04下安…

JVM 垃圾回收详解之内存分配和回收原则+死亡对象判断方法

前言 当需要排查各种内存溢出问题、当垃圾收集成为系统达到更高并发的瓶颈时,我们就需要对这些“自动化”的技术实施必要的监控和调节。 堆空间的基本结构 Java 的自动内存管理主要是针对对象内存的回收和对象内存的分配。同时,Java 自动内存管理最核…

【STM32】基础知识 第七课 存储器映射 寄存器映射

【STM32】基础知识 第七课 存储器映射 & 寄存器映射 STM32 寻址范围存储器映射存储器功能划分 (F1 为例)Block 0Block 1Block 2寄存器映射 寄存器映射 (F1 为例)寄存器映射举例寄存器地址计算GPIO 外设基地址及偏移量寄存器地址及偏移量寄存器地址计算过程 使用结构体映射寄…

《2-数组》

数组 1.简介: 数组(Array)是一种固定长度的存储相同数据类型在连续内存空间中的数据结构 引出:[索引 (Index)]----元素在数组中的位置 2.初始化 写法:一般用到无初始值、给定初始值 在不给定…

中国制造业连续13年全球第一,MES管理系统,打造竞争新优势

根据工业和信息化部最近发布的数据,在2022年,中国的制造业增加值在全球的占比接近30%,制造业规模已连续13年位居世界第一。根据国家统计局的最新数字,一到二月份,我国的生产值与去年同期相比上升了2.1&…

实现声明式锁,支持分布式锁自定义锁、SpEL和结合事务

目录 2.实现 2.1 定义注解2.2 定义锁接口2.3 锁的实现 2.3.1 什么是SPI2.3.2 通过SPI实现锁的多个实现类2.3.3 通过SPI自定义实现锁3.定义切面 3.1 切面实现3.2 SpEL表达式获取动态key3.3 锁与事务的结合4.测试 4.1 ReentrantLock测试4.2 RedissonClient测试4.3 自定义锁测试5…

移动硬盘如何分区?教您快速解决!

案例:怎么对移动硬盘进行分区? 【我平常找一个文件需要耗费很长时间,十分麻烦。我现在想通过对移动硬盘进行分区的方式,整理好我的文件,方便使用时查找。有没有人知道移动硬盘怎么分区?教教我!…

深入浅出JS定时器:从setTimeout到setInterval

前言 当谈到 JavaScript 编程语言最基本的概念时,定时器就是一个必须掌握的知识点。在编写网站时,你经常会遇到需要在一定时间间隔内执行一些代码的情况。这时候,JavaScript 定时器就可以派上用场了。 什么是定时器? JS 定时器是…

[Gitops--2]Argocd和Gitlab-runner安装配置

ArgoCd Argo是一组k8s原生工具集,用于运行和管理k8s上的作业和应用程序.Argo提供了一种在k8s上创建工作和应用的三种计算模式:服务模式,工作流模式和基于事件模式.所有的Argo工具都实现为了创建控制器和自定义资源. 为什么选ArgoCD 应用程序的定义,配置和环境都应该是声明性…

ChatGPT和GPT-4帮你写人物传记

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…

研读Rust圣经解析——Rust learn-11(测试,迭代器,闭包)

研读Rust圣经解析——Rust learn-11(测试,迭代器,闭包) 测试编写测试模块声明test模块编写测试方法执行测试测试结果检查 闭包定义一个闭包完整写法闭包可以捕获环境闭包类比函数闭包类型推断闭包获取所有权将被捕获的值移出闭包和…

Jenkins配置邮件通知

1、下载Email Extension插件 2、配置发件人邮箱地址 系统管理 > 系统配置 3、配置邮件通知 系统管理 > 系统配置 > 邮件通知 往下滑找到 通过发送测试邮件测试配置 测试 如果以上配置没有问题,会发送一封测试邮件到服务器中,如果有问题请优先检查一下端口号和是…

网络协议-HTTP协议详情讲解

目录 HTTP协议内容和方法 HTTP请求常见请求头 HTTP常见返回头 HTTP协议基本方法 常见HTTP状态码 面试解惑:301 vs 308 面试解惑:302 / 303 / 307 常见HTTP头 User-Agent Content-Type Origin Accept Referer Connection HTTP协议内容和方法…

Nginx中location规则 与 URL重写(rewrite)详解

1.Nginx中location与rewrite 1.1 location与rewrite常用的正则表达式 符号作用^匹配输入字符串的起始位置$ 匹配输入字符串的结束位置*匹配前面的字符零次或多次。如“ol*”能匹配“o”及“ol”、“oll” 匹配前面的字符一次或多次。如“ol”能匹配“ol”及“oll”、“olll”…

微信为什么使用 SQLite 保存聊天记录

SQLite “只是”一个库,它不是传统意义上的服务器。因此,在某些场合下,它确实不合适。但是,在相当多的其他场合,它却是最合适的选择。SQLite 号称是部署和使用最广泛的数据库引擎。我认为这很有可能,因为 S…

《PyTorch 深度学习实践》第10讲 卷积神经网络(基础篇)

文章目录1 卷积层1.1 torch.nn.Conv2d相关参数1.2 填充:padding1.3 步长:stride2 最大池化层3 手写数字识别该专栏内容为对该视频的学习记录:【《PyTorch深度学习实践》完结合集】 专栏的全部代码、数据集和课件全放在个人GitHub了&#xff…

SpringCloud之OpenFeign介绍案例+相关面试题

概述 OpenFeign是一个声明式的WEB服务客户端,它使WEB服务客户端变得更加容易。具有可插拔的注解支持,SpringCloud中添加了SpringMVC注解的支持。SpringCloud中集成了Ribbon和Eureka,以及SpringCloud LoadBalance,以便在使用Feign时…

C++数据结构:树

树 树是一种数据结构,它是n(n>0)个节点的有限集。n0时称为空树。n>0时,有限集的元素构成一个具有层次感的数据结构。 根 有且仅有一个结点的非空树,那个结点就是根。 A就是上面树的根节点 子树 在一棵非空树中,除根外&a…

由浅入深,一文彻底搞懂Mybatis+面试题分享

mybatis常见面试题链接:2023年-Mybatis常见面试题_是Smoky呢的博客-CSDN博客 MVC架构模式和三层架构 在说Mybatis之前,需要知道MVC架构模式和三层架构的这种思想 MVC架构模式 M:Model,数据层。都是和数据相关,比如实体…

MongoDB实现---事务机制

事务机制 原子性是MongoDB实现事务的难点,隔离性和持久性则是MongoDB事务机制的亮点 ACID支持:由于前面说过MongoDB是基于大数据、提供高度可扩展和高可用;所以其事务机制不仅仅是一般ACID还是结合了BASE理论下的ACID 原子性:保…