【Javassist】快速入门系列12 当检测到catch语句时在catch前插入代码

news2024/11/17 1:36:18

系列文章目录

01 在方法体的开头或结尾插入代码
02 使用Javassist实现方法执行时间统计
03 使用Javassist实现方法异常处理
04 使用Javassist更改整个方法体
05 当有指定方法调用时替换方法调用的内容
06 当有构造方法调用时替换方法调用的内容
07 当检测到字段被访问时使用语句块替换访问
08 当检测到对象(不包括数组)创建时用代码块替换
09 当检测到对象(不包括数组)创建时用代码块替换
10 当检测到instanceof表达式时用代码块替换
11 当检测到显示类型转换时用代码块替换
12 当检测到catch语句时在catch前插入代码


文章目录

  • 系列文章目录
  • 前言
  • 引入Javassist jar包
    • 当检测到catch语句时在catch前插入代码
  • 总结
  • 说明


前言

上一章我们介绍了当检测到显示类型转换时用代码块替换,学习了 method.instrument的用法。以及参数为Cast的重载方法edit的含义。本章主要介绍当检测到catch语句时在catch前插入代码。


引入Javassist jar包

在上几篇文章已经引入了javassist的jar包,如果你是第一次观看本系列文章,也可以复制以下maven依赖将jar包导入工程。

        <dependency>
            <groupId>org.javassist</groupId>
            <artifactId>javassist</artifactId>
            <version>3.28.0-GA</version>
        </dependency>

当检测到catch语句时在catch前插入代码

/**
 * 【Javassist】快速入门系列11 当检测到显示类型转换时用代码块替换
 * 公众号&B站:精致的王同学
 * @author 精致的王同学
 * @date 2022/12/28 18:18
 */
public class Basic12Handler {
    public static void main(String[] args) throws Exception{
        // 获取javassist默认类池
        ClassPool pool = ClassPool.getDefault();
        // 获取basic.Basic12Test的ctclass类
        CtClass ctClass = pool.get("basic.Basic12Test");
        // 获取basic.Basic12Test的main方法
        CtMethod method = ctClass.getDeclaredMethod("main");
        // 当检测到catch语句时在catch前插入代码
        method.instrument(new ExprEditor() {
            @Override
            public void edit(Handler h) throws CannotCompileException {
                try {
                    if (h.getType().equals(pool.get("java.lang.Exception"))) {
                        h.insertBefore("System.out.println(\"Handler\");");
                    }

                } catch (NotFoundException e) {
                    e.printStackTrace();
                }
            }
        });
        // 将类写成文件
        ctClass.writeFile();
        // 获取修改后的class文件
        Class<?> clazz = ctClass.toClass();
        // 获取修改后的类实例
        Object obj = clazz.newInstance();
        // 获取修改后的main方法
        Method main = clazz.getDeclaredMethod("main", String[].class);
        // 调用修改后的main方法
        main.invoke(obj,(Object) new String[0]);
    }
}

以上Basic12Handler 类创建了一个main方法,该方法中首先获取javassist的类池pool,然后调用pool.get(“basic.Basic12Test”)方法获取到basic包下的Basic12Test类。Basic12Test类源码如下:

/**
 * 第12节测试类
 * 公众号&B站:精致的王同学
 * @author 精致的王同学
 * @date 2022/12/28 17:54
 */
public class Basic12Test {
    public static void main(String[] args) {
        SkuService skuService = new SkuService();
        try {
            skuService.getSkuProfitRate(1L);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

该类中有一个main方法,创建了一个skuService 对象。然后将调用其getSkuProfitRate方法。如果有异常则打印异常,SkuService 类源码如下:

/**
 * 商品业务类
 *
 * @author 精致的王同学
 * @date 2022/12/19 23:38
 */
public class SkuService {
    public BigDecimal getSkuProfitRate(Long skuId){
        // 模拟调用查价格接口获取商品原价和商品销售价
        BigDecimal originalPrice = null;
        originalPrice = getOriginalPrice(skuId);
        BigDecimal salePrice = getSalePrice(skuId);
        BigDecimal profit = salePrice.subtract(originalPrice);
        return profit.divide(originalPrice);
    }

    private BigDecimal getSalePrice(Long skuId) {
        return new BigDecimal(130.00);
    }

    private BigDecimal getOriginalPrice(Long skuId) {
        // 模拟sku原始价格为0,价格未初始化的情况
        BigDecimal originalPrice = new BigDecimal(0.00);
        if (BigDecimal.ZERO.compareTo(originalPrice) == 0) {
            throw new ErrorCodeException(10001,"sku原始价格不能等于0!");
        }
        return originalPrice;
    }
}

SkuService类的getSkuProfitRate方法根据skuId获取其sku利润率。其中调用getOriginalPrice方法抛出一个异常。

回到Basic12Test的main方法,在获取到Basic12Test类的ctClass的对象之后,获取其main方法的方法对象。

接着调用method.instrument(ExprEditor editor)方法搜索method内的catch语句。调用h.getType()方法获取异常类型的ctclas文件判断是否是java.lang.Exception类型的,如果是则调用h.insertBefore(“System.out.println(“Handler”);”);在catch前插入代码。

instrument方法接收一个ExprEditor 类型的对象,该类有很多重载的edit方法,其中参数为Handler的重载方法代表搜索方法内的catch语句。

在replace的代码块中,以下符号有特殊含义:

$1  catch子句捕获的异常对象。
$r  catch子句捕获的异常的类型。它用于强制转换表达式中。
$w  包装器类型。它用于强制转换表达式中。
$type  java.lang.Class对象表示catch子句捕获的异常的类型。

最后模拟调用修改后的main方法结果如下:
main方法结果

总结

本篇文章介绍了使用Javassist当检测到catch语句时在catch前插入代码,学习了 method.instrument的用法。以及参数为Handler的重载方法edit的含义。

说明

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

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

相关文章

【C++学习】vector的使用及模拟实现

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《C学习》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; vector的使用及模拟实现&#x1f387;构造函数&#x1f9e8;模拟实现&#x1f9e8;vector的扩容机制&…

力扣(LeetCode)363. 矩形区域不超过 K 的最大数值和(2022.12.30)

给你一个 m x n 的矩阵 matrix 和一个整数 k &#xff0c;找出并返回矩阵内部矩形区域的不超过 k 的最大数值和。 题目数据保证总会存在一个数值和不超过 k 的矩形区域。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,0,1],[0,-2,3]], k 2 输出&#xff1a;2 解释&…

2022年-年度总结报告

目录1.攻克的技术难题问题1&#xff1a;2.学习的新技术1.system系统的学习2.网络3.游戏22年总结23年的计划1.先给自己画个大饼2.计划内的小饼1.攻克的技术难题 问题1&#xff1a; 跑VTS测试的时候&#xff0c;mkfs.exfat挂测失败&#xff0c;VTS刷最新的谷歌gsi没有过&#x…

大文件传输如何帮助媒体行业

过去几年&#xff0c;随着分辨率从4k到6k再到8k的升级&#xff0c;观众已经适应了高分辨率的时代。然而&#xff0c;许多媒体工作室的工作流程还停留在过去。 TB甚至PB大小的材料的传输让从业者无所适从。这就是高速文件传输对媒体行业有很大帮助的原因。 什么是大文件传输&am…

81.【SpringMVC】

SpringMVC(一)、认识MVC三层架构1.回顾MVC(1).什么是MVC三层框架(2).MVC要做那些事情?(3).常见的MVC三层框架结构(4).知识拓展2.代码回顾3.什么是SpringMVC(二)、第一个SpringMVC0.前提1.搭建环境2.配置WEB-INF的XML配置文件3.在资源Resource的包下设置springmvc-servlet.xml4…

30-深入Hotspot源码与Linux内核理解NIO/BIO/AIO

IO模型 IO模型就是说用什么样的通道进行数据的发送和接收&#xff0c;Java共支持3种网络编程IO模式&#xff1a;BIO&#xff0c;NIO&#xff0c;AIO BIO(Blocking IO) 同步阻塞模型&#xff0c;一个客户端连接对应一个处理线程 缺点&#xff1a; 1、IO代码里read操作是阻塞操…

Spreadsheet与FineReport数据集对比

什么是数据集&#xff1f;在BI工具中指的是在报表开发前的取数过程&#xff0c;把需要的数据整合成一个数据集合&#xff0c;以便于在报表开发中使用。可以把它理解为我们基于数据库获取我们需要的数据。而数据库获取数据是有多种方式的&#xff0c;比如可以通过直接写SQL语句、…

基于verilog实现序列相关检测

题目来源牛客网&#xff0c;完整工程源码&#xff1a;https://github.com/ningbo99128/verilog 目录 1、VL25 输入序列连续的序列检测 题目介绍 思路分析 代码实现 仿真文件 2、VL26 含有无关项的序列检测 题目介绍 思路分析 代码实现 仿真文件 3、VL27 不重叠序列检…

Sleuth+Zipkin架构

为什么要链路追踪 小结&#xff1a; nacos 【name server】&#xff1a;注册中心&#xff0c;解决服务的注册与发现 nacos【config】&#xff1a;配置中心&#xff0c;微服务配置文件的中心化管理&#xff0c;同时配置信息的动态刷新 Ribbon&#xff1a;客户端负载均衡器&#…

《设计模式》享元模式

《设计模式》享元模式《设计模式》设计模式的基本原则 《设计模式》单例模式 《设计模式》工厂模式 《设计模式》原型模式 《设计模式》建造者模式 《设计模式》适配器模式 《设计模式》桥接模式 《设计模式》装饰者模式 《设计模式》组合模式 《设计模式》外观模式 《设计模式…

数据结构课设:迷宫问题

文章目录前言一、概要设计1、基本信息2、功能模块图3、功能描述4、调用关系图5、结果演示① 创建迷宫② 求解③ 清除多余路径二、完整代码前言 最近刚好在写自己的课设&#xff0c;匆匆忙忙写出来的课设系统&#xff0c;仍有不足&#xff0c;拿出来和大家分享一下&#xff0c;…

C. p-binary(二进制位)

Problem - 1225C - Codeforces Vasya会看中任何数字&#xff0c;只要它是2的整数次方。另一方面&#xff0c;Petya非常保守&#xff0c;只喜欢单一的整数p&#xff08;可以是正数、负数或零&#xff09;。为了结合他们的口味&#xff0c;他们发明了2xp形式的p-二进制数&#xf…

jmeter接口测试之导入测试用例/get请求中Url存在参数(工作日记2)

导入接口用例进行接口测试 以运营中心测试计划中的企业菜单管理为例 【前提条件】 1、有接口数据 2、有接口用例 我们需要把接口测试用例转换为CSV格式步骤如下&#xff1a; 右键选择打开方式为Notepad 需要将文件设置一下编码 文件留着备用 【步骤】 1、新建一个企业…

前端基础之PS和相关基础知识总结

PS安装&#xff1a; 淘宝 PS简介 面板简介&#xff08;菜单栏、工具栏、辅助面板&#xff09; 图片格式&#xff1a; jpgjpeg&#xff08;色彩丰富的图片&#xff09;png&#xff08;半透明图片&#xff09;gif&#xff08;网页动态图&#xff09;psd&#xff08;ps设计源文…

android java udp广播 用于局域网搜索扫描设备。

DatagramSocket socket new DatagramSocket();//设置接收等待时长socket.setSoTimeout(LanCommConfig.RECEIVE_TIME_OUT);byte[] sendData new byte[1024];//使用广播形式&#xff08;目标地址设为255.255.255.255&#xff09;的udp数据包DatagramPacket sendPacket new Dat…

STC15单片机+DS18B20+LCD1602+PCF8574转IIC接口温度显示

STC15单片机+DS18B20+LCD1602+PCF8574转IIC接口温度显示 📺显示效果 LCD1602 IIC接口 ✨本示例基于自制的STC开发板,主控采用的:IAP15W4K61S4相关篇《【PCB开源分享】STC/IAP15W4K61S4开发板》《【开源分享】自制STC15W408AS开发板》🌼接线说明 🌿CD1602+PCF8574转IIC接…

stlink下载调试器使用说明(STM32采用stlink下载程序)

stlink能干什么&#xff1f; 最基本的功能&#xff1a;下载程序。 一般STM32支持ISP串口下载&#xff0c;也支持stlink、jlink等下载器下载 。 使用stlink、jlink下载要比串口方便很多&#xff0c;在keil里直接点击下载就行了&#xff0c;不需要去选择hex文件&#xff0c;速度…

你可能还不知道 golang 的高效编码细节

xdm&#xff0c;我们都知道 golang 是天生的高并发&#xff0c;高效的编译型语言 可我们也都可知道&#xff0c;工具再好&#xff0c;用法不对&#xff0c;全都白费&#xff0c;我们来举 2 个常用路径来感受一下 struct 和 map 用谁呢&#xff1f; 计算量很小的时候&#xf…

特斯拉第10000桩落成,百度地图送10000名充电免单!

「导语」 为庆祝特斯拉在中国大陆落成第10000个超级充电桩&#xff0c;百度地图推出特斯拉车主专属权益。车主们通过百度地图APP&#xff0c;即可实时获取超级充电桩空闲信息、一键规划专属充电路线。12.28-1.2期间&#xff0c;更有10000份充电免单福利限时放送。 在汽车电动…

Linux环境开机自启java应用

Linux环境设置开机自启java应用&#xff08;Linux定时任务&#xff09; crontab是Unix和Linux用于设置需要周期性被执行的指令&#xff0c;是Linux服务器很常用的技术&#xff0c;很多任务都会设置在crontab循环执行。 crontab &#xff1a; 提供给用户控制任务计划的命令&…