【Javassist】快速入门系列05 当有指定方法调用时替换方法调用的内容

news2025/4/19 9:52:35

系列文章目录

01 在方法体的开头或结尾插入代码
02 使用Javassist实现方法执行时间统计
03 使用Javassist实现方法异常处理
04 使用Javassist更改整个方法体
05 当有指定方法调用时替换方法调用的内容


文章目录

  • 系列文章目录
  • 前言
  • 引入Javassist jar包
    • 当有指定方法调用时替换方法调用的内容
  • 总结
  • 说明


前言

上一章我们介绍了使用Javassist更改整个方法体,学会了Javassist的setBody()方法使用。本章主要介绍当检测到指定方法调用时替换方法调用的内容,method.instrument方法的使用。


引入Javassist jar包

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

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

当有指定方法调用时替换方法调用的内容

/**
 * 【Javassist】快速入门系列05 当有指定方法调用时替换方法调用的内容
 * 公众号&B站:精致的王同学
 * @author 精致的王同学
 * @date 2022/12/21 16:25
 */
public class Basic05MethodCall {
    public static void main(String[] args) throws Exception{
        // 获取javassist默认类池
        ClassPool pool = ClassPool.getDefault();
        // 获取basic.Basic05Test的CtClass对象
        CtClass ctClass = pool.get("basic.Basic05Test");
        // 获取Basic05Test类的main方法
        CtMethod method = ctClass.getDeclaredMethod("main");
        // 更改main方法的方法体
        method.instrument(new ExprEditor(){
            @Override
            public void edit(MethodCall m) throws CannotCompileException {
                if (m.getClassName().equals("basic.StockService") && m.getMethodName().equals("queryStockNum")) {
                    m.replace("{System.out.println(\"MethodCall\");$_ = $proceed($$);}");
                }
            }
        });
        // 将类写成文件
        ctClass.writeFile();
        // 获取basic.Basic05Test的clazz对象
        Class<?> clazz = ctClass.toClass();
        // 获取修改后的basic.Basic05Test的实例
        Object obj = clazz.newInstance();
        // 获取修改后的main方法
        Method main = clazz.getDeclaredMethod("main",String[].class);
        // 模拟调用修改后的main方法
        main.invoke(obj,(Object) new String[0]);
    }
}

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

/**
 * 第5节测试类
 * 公众号&B站:精致的王同学
 * @author 精致的王同学
 * @date 2022/12/21 17:24
 */
public class Basic05Test {
    public static void main(String[] args) throws Exception{
        StockService stockService = new StockService();
        stockService.queryStockNum(1l);
    }
}

该类中调用了StockService 的stockService方法。StockService 源码如下:

/**
 * 库存业务类
 * 公众号&B站:精致的王同学
 * @author 精致的王同学
 * @date 2022/12/19 17:25
 */
public class StockService {
    public Integer queryStockNum(Long skuId) throws Exception {
        // 调用库存数量接口
        Random random = new Random();
        Long mills = Long.valueOf(random.nextInt(5)*1000);
        // 模拟接口调用耗时
        Thread.sleep(mills);
        return 0;
    }
}

StockService 的queryStockNum方法用于模拟调用获取sku库存数量接口的调用。

回到Basic05MethodCall 的main方法,在获取到Basic05Test类的ctClass的对象之后,获取其main方法的方法对象。然后调用method.instrument(ExprEditor editor)方法搜索类型为方法调用的语句。

instrument方法接收一个ExprEditor 类型的对象,该类有很多重载的edit方法,其中参数为MethodCall 的重载方法代表搜索method方法内的方法调用。然后判断如果是basic.StockService类的queryStockNum方法调用,则将此方法调用替换为指定代码块的内容。

ExprEditor 类重载的edit方法如下:
ExprEditor 类重载的edit方法

如果指定方法的调用有返回值的话,必须指定其内容。$_ 代表方法调用的返回值。

$proceed 代表调用指定的方法,本例中为queryStockNum方法。

$$ 代表方法的全部参数。

new ExprEditor() 代码块中的内容所做的事情为搜索main方法中所有的方法调用,当方法调用是basic.StockService类的queryStockNum方法时在屏幕上打印MethodCall。

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

总结

本篇文章介绍了使用Javassist当有指定方法调用时替换方法调用的内容,学习了 method.instrument的用法。以及参数为MethodCall 的重载方法的含义。

说明

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

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

相关文章

1. 位1的个数

文章目录题目解法一&#xff1a;右移统计解题思路代码实现复杂度分析解法二&#xff1a;清除最低位解题思路代码实现复杂度分析解法三&#xff1a;分治解题思路代码实现复杂度分析解法四&#xff1a;JDK Integer.bitCount(int i)代码实现题目 编写一个函数&#xff0c;输入是一…

DPU02:国产USB转UART的桥接控制器兼容替代CP2102

目录DPU02芯片特性USB配置数据和序列号设置DPU02应用领域DPU02是高度集成的USB转UART的桥接控制器芯片&#xff0c;可将RS-232设计更新为USB设计&#xff0c;并简化PCB组件空间。DPU02包括了一个USB 2.0全速功能控制器、USB收发器、振荡器、EEPROM和带有完整调制解调控制信号的…

一文详解深度学习冷板式液冷散热技术规范及要求

深度学习 | 东数西算 | 液冷散热 数据挖掘 | 数据分析 | 高性能计算 随着深度学习、东数西算、医药研发、数据分析、数据挖掘、遥感测绘、高性能计算等技术的快速发展&#xff0c;数据中心的创建与日俱增&#xff0c;传统的风冷散热方式已经不同满足数据中心散热的需求&#x…

Huffman二进制编码以及文本的压缩与解压

目录Huffman树转化成二进制编码文本压缩文本解压Huffman树转化成二进制编码 在上一篇博客的末尾&#xff0c;将Huffman树转化成了01 构成的字符串&#xff0c;显然在实际应用中不是这种操作。我们实际想要的是01构成的一串bits&#xff1b;举个例子&#xff1a;字符"A&quo…

HTTP权威指南------URL与资源

目录 URL标准格式 URL快捷方式 动扩展URL 字符 方案详解 web基础中介绍了URI、URL与URN&#xff1b; URI是一类更通用的资源标识符&#xff0c;URL是它的一个子集&#xff1b; URI是一个通用的概念&#xff0c;它主要由URL与URN组成&#xff1b; URL是通过描述资源的位…

【Kafka】Linux下搭建kafka服务,完整学习案例

【Kafka】Linux下搭建kafka服务&#xff0c;完整学习代码案例&#xff08;一&#xff09;Kafka架构基础【1】图解kafka是什么&#xff1f;&#xff08;1&#xff09;为什么需要消息队列&#xff08;2&#xff09;Topic主题&#xff08;3&#xff09;分区&#xff08;4&#xff…

【UE4 第一人称射击游戏】06-设置动画角色2

步骤&#xff1a; 1.打开“WalkRun_BS”&#xff0c;将最左边中间的点和最右边中间的点的动画改为“walk_backward_inPlace” 2.打开“SWAT_AnimBP”&#xff0c;双击“Walk_Run” 双击“Walk_Run” 将混合空间“WalkRun_BS”拖入 将“Direction”和“Speed”提升为变量&#…

车载以太网 - 初识DoIP - 01

1、DoIP是什么? 从表达形式上 它就是UDS诊断套上车载以太网的马甲,然后实现UDS诊断的所有内容。通过下图DoIP的报文帧格式,从下面往上看,最尾部的数据我们能够很清晰的看到,User Data实际上就是UDS诊断数据,比如:10 03亦或是22 F1 86等信息。然后再往前就是源地址和目标…

Python通过Spleeter实现音唱人声(歌声)伴奏分离

程序示例精选 Python实现音唱人声(歌声)伴奏分离 如需安装运行环境或远程调试&#xff0c;见文章底部微信名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对《Python实现音唱人声(歌声)伴奏分离》编写代码&#xff0c;功能包括了人声(歌声)-伴奏分离。运…

Dubbo、Spring Cloud和kubernetes该如何选型?

文章目录背景微服务的公共关注点微服务平台的选型横向比对微服务优劣比对背景 做技术选型。如果缺乏足够的经验&#xff0c;对so a啊&#xff0c;微服架构原理以及整个行业服务化演进的历史缺乏了解。 那么&#xff0c;对这个三个产品该如何选择啊&#xff1f;的确会感到困惑。…

想做副业怎么才能找到适合的项目,六条建议让你找副业不再迷茫

大家好&#xff0c;我是蝶衣王的小编 现在疫情反复&#xff0c;赚钱太难了。许多年轻人想发展副业。而现实情况往往是不知道做什么以及如何做&#xff0c;这是非常令人困惑的。我在这里分享六个要点&#xff0c;让你找到合适的项目。 六个步骤分别是 会观察、观察相关信息和赚…

有趣的网站分享——福音戰士標題生成器

说起文字标题生成器其实也是有一定的历史了。 他们往往源于某种媒介所带来的个性化标题的出现&#xff08;比如动画或电影、广告、产品Logo等&#xff09;。 被互联网群众察觉分享后在模因传播的现象下深入人心。 比如下面这样的&#xff1a; 就出自知名交友网站P…… 额咳。…

快速入门Spring MVC 一篇就够了

前言 我们前面学习了Spring两大核心机制IoC和AOP&#xff0c;接下来我们一起来学习Spring MVC。这篇文章带你快速入门Spring MVC。 Spring MVC概述 Spring MVC是目前主流的实现MVC设计模式的框架&#xff0c;是Spring框架的一个分支产品&#xff0c;以Spring loC容器为基础&…

Fabric.js 铅笔笔刷

本文简介 点赞 关注 收藏 学会了 fabric.js 的铅笔其实是继承基础画笔的一个工具&#xff0c;在基础画笔的基础上多了“拐角平滑度”等配置项。 本文讲解铅笔的基础用法以及常用事件。 常规配置 真实世界的铅笔有不同的型号&#xff0c;颜色的深浅、笔芯的硬度都是不同的…

90后,27岁转行软件测试,从月入3000+到月薪过万,打开了人生新篇章~

承蒙时光不弃&#xff0c;感谢努力的自己。以前总是在某些鸡汤文中看到这句话&#xff0c;当时觉得过于矫情&#xff0c;而如今当我突破重重困难成功转行&#xff0c;收获了更好的人生后&#xff0c;才发自内心的也有了这样的感叹。 几个月的努力和辛劳&#xff0c;一时之间难以…

转互联网好难,如何避免无效转行?

如果你现在是在传统行业工作&#xff0c;想转行互联网&#xff0c;应该怎么做呢&#xff1f; 很多人经常会担心自己的行业、专业、年龄等等会是障碍&#xff0c;或者自己没有经验&#xff0c;去面试的时候公司却都需要相关经验的人&#xff0c;怎么办呢&#xff1f; 这篇文章…

图形驱动软件栈

图形驱动软件栈 HINZER&#xff0c;2022年&#xff0c;我在北京。芯片设计行业&#xff0c;GPU 固件和驱动开发&#xff0c;对嵌入式系统感兴趣。 1 说明背景 1.1 近来想法 做了一段时间的 GPU 固件和驱动开发&#xff0c;加上平时学习的一些零散的知识&#xff0c;最近打算整…

【Web前端HTML5CSS3】06、盒模型

六、盒模型 1、文档流&#xff08;normalflow&#xff09; 网页是一个多层的结构&#xff0c;一层摁着一层 通过 CSS 可以分别为每一层来设置样式&#xff0c;作为用户来讲只能看到最顶上一层 这些层中&#xff0c;最底下的一层称为文档流 文档流是网页的基础我们所创建的元…

牛客java刷题知识点总结(八)

方法调用 类中变量&#xff1a; 除了private权限外&#xff0c;其他权限的变量&#xff08;没有表示默认default&#xff09;&#xff0c;均可以用“对象.变量名”来调用。对于private变量&#xff0c;即使使用static&#xff0c;也不能用“类.变量名”来调用私有变量。只能通过…

UID走私:一种在线跟踪用户的新技术

©网络研究院 几十年来&#xff0c;广告商和网络追踪者已经能够在用户访问的所有网站上汇总用户信息&#xff0c;主要是通过在用户的浏览器中放置第三方cookies。 两年前&#xff0c;几个优先考虑用户隐私的浏览器开始默认屏蔽所有用户的第三方cookies。 对于那些代表其…