【Javassist】快速入门系列03 使用Javassist实现方法异常处理

article/2025/9/15 5:04:13

系列文章目录

01 在方法体的开头或结尾插入代码
02 使用Javassist实现方法执行时间统计
03 使用Javassist实现方法异常处理


文章目录

  • 系列文章目录
  • 前言
  • 引入Javassist jar包
    • 使用Javassist实现方法异常处理
  • 总结
  • 说明


前言

上一章我们介绍了使用使用Javassist实现了对方法执行时间的统计,学会了Javassist在方法体前后插入代码和为类新增字段。本章主要介绍使用Javassist为方法实现异常处理。


引入Javassist jar包

在上几篇文章已经引入了javassist的jar包,如果你是第一次观看本系列文章,也可以复制以下maven依赖将jar包导入工程。本篇文章还用到了commons-lang3jar包中的org.apache.commons.lang3.exception.ExceptionUtils工具类。

        <dependency><groupId>org.javassist</groupId><artifactId>javassist</artifactId><version>3.28.0-GA</version></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.7</version></dependency>

使用Javassist实现方法异常处理

/*** 【Javassist】快速入门系列03 使用Javassist实现方法异常处理* 公众号&B站:精致的王同学* @author 精致的王同学* @date 2022/12/19 22:31*/
public class Basic03ExceptionHandle {public static void main(String[] args) throws Exception {// 创建javassist默认类池ClassPool pool = ClassPool.getDefault();//获取basic.SkuService的Ctclass文件CtClass ctClass = pool.get("basic.SkuService");// 获取SkuService的getSkuProfitRate方法CtMethod method = ctClass.getDeclaredMethod("getSkuProfitRate");// 获取要捕获的异常类型CtClass etype  = pool.get("basic.ErrorCodeException");// 给方法添加异常处理method.addCatch("{ System.out.println(org.apache.commons.lang3.exception.ExceptionUtils.getStackTrace($e));;\n " +"//todo 模拟将异常错误码、提示及堆栈信息插入数据库 \n" +" throw $e;}",etype);// 将类写入文件ctClass.writeFile();// 获取类的clazz文件Class<?> skuServiceClazz = ctClass.toClass();// 实例化类的对象Object obj = skuServiceClazz.newInstance();// 获取类的修改后方法Method getSkuProfitRate = skuServiceClazz.getDeclaredMethod("getSkuProfitRate",Long.class);// 调用修改后的getSkuProfitRate方法Object skuProfitRate = getSkuProfitRate.invoke(obj, (Object) 1l);System.out.println("sku的利润率为:"+skuProfitRate);}
}

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

/*** 库存业务类* 公众号&B站:精致的王同学* @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;}
}

该类主要模拟获取sku销售利润比例。利润比例=(销售价-原价)/原价

回到Basic03ExceptionHandle的main方法中,在获取到basic.SkuService的ctClass对象后,获得了其声明的getSkuProfitRate方法的CtMethod对象。

然后通过调用pool.get(“basic.ErrorCodeException”)方法获取要捕获的异常类型,其中basic.ErrorCodeException的源码如下:

/*** 库存业务类* 公众号&B站:精致的王同学* @author 精致的王同学* @date 2022/12/19 23:38*/
public class ErrorCodeException extends RuntimeException {private Integer code;private String msg;public ErrorCodeException(Integer code, String msg) {this.code = code;this.msg = msg;}public ErrorCodeException(String message, String msg) {super(message);this.msg = msg;}public Integer getCode() {return code;}public String getMsg() {return msg;}
}

然后调用method.addCatch(String src, CtClass exceptionType)方法为getSkuProfitRate方法添加catch语句。其中addCatch的第一个参数为catch子句中要执行的代码块,第二个参数为要捕获的异常类型。此例中为ErrorCodeException 的Ctclass类型。

我们捕获到错误码异常之后,在实际生产场景想要对异常错误码,错误信息,及堆栈信息插入到数据库中。后续在做个管理功能,方便研发排查错误。在此例中省略这些语句。其中$e代表被捕获的异常对象。拿到此对象便可拿到异常的详细信息。同时我们需借用org.apache.commons.lang3.exception.ExceptionUtils.getStackTrace(e)获取异常的堆栈信息。

注意addCatch方法需以throw或return语句结尾。

最后调用 模拟调用javassist修改后的getSkuProfitRate方法。输出结果为:
getSkuProfitRate方法输出结果

总结

本篇文章介绍了使用Javassist实现方法异常处理,学习了Javassist的addCatch语句的用法。通过调用CtMethod的addCatch方法可以拦截特定类型的异常并对其进行处理。

说明


http://chatgpt.dhexx.cn/article/O4XSUwAh.shtml

相关文章

【Javassist】快速入门系列04 使用Javassist更改整个方法体

系列文章目录 01 在方法体的开头或结尾插入代码 02 使用Javassist实现方法执行时间统计 03 使用Javassist实现方法异常处理 04 使用Javassist更改整个方法体 文章目录 系列文章目录前言引入Javassist jar包使用Javassist更改整个方法体 总结说明 前言 上一章我们介绍了使用Ja…

Java字节码编程之非常好用的javassist

我为什么要研究这个&#xff1f; 因为我在开发一个框架的时候需要用到。 我开发的这个框架&#xff0c;有一个注解&#xff0c;当用户输入变量名&#xff0c;类名的时候&#xff0c;我这个框架可以为其自动生成一个对象&#xff0c;并加载到内存中供以后使用。 这个小功能可…

javassist学习

Java 字节码以二进制的形式存储在 .class 文件中&#xff0c;每一个 .class 文件包含一个 Java 类或接口。Javaassist 就是一个用来 处理 Java 字节码的类库。它可以在一个已经编译好的类中添加新的方法&#xff0c;或者是修改已有的方法&#xff0c;并且不需要对字节码方面有深…

Javassist

Javassist Javassist是一个开源的分析、编辑和创建Java字节码的类库&#xff0c;可以直接编辑和生成Java生成的字节码。 相对于bcel, asm等这些工具&#xff0c;开发者不需要了解虚拟机指令&#xff0c;就能动态改变类的结构&#xff0c;或者动态生成类。javassist简单易用&…

[Java基础]—Javassist

Javassist Javassist (JAVA programming ASSISTant) 是在 Java 中编辑字节码的类库;它使 Java 程序能够在运行时定义一个新类, 并在 JVM 加载时修改类文件。原理与反射类似&#xff0c;但开销相对较低。 常用API ClassPool getDefault : 返回默认的 ClassPool 是单例模式的&…

Javassist基本用法

Javassist概述 Javassist是可以动态编辑Java字节码的类库。它可以在Java程序运行时定义一个新的类&#xff0c;并加载到JVM中&#xff1b;还可以在JVM加载时修改一个类文件&#xff0c;添加新的方法&#xff0c;或者是修改已有的方法。Javassist使用户不必关心字节码相关的规范…

Java中的高性能字节码工具:Javassist

前言 一般常见的动态方法调用使用Reflection或者字节码生成技术。虽然JDK已对反射进行了优化但在追求性能的场景中仍然显得性能不佳。本文即是介绍一个面向程序员友好的字节码操作类库javassist。根据benchmark其展现的性能已几乎无异于直接调用。 开源地址&#xff1a;javas…

Java字节码技术javassist

一、Javassist入门 &#xff08;一&#xff09;Javassist是什么 Javassist是可以动态编辑Java字节码的类库。它可以在Java程序运行时定义一个新的类&#xff0c;并加载到JVM中&#xff1b;还可以在JVM加载时修改一个类文件。Javassist使用户不必关心字节码相关的规范也是可以编…

java--javassist学习

Javassist是一个开源的分析、编辑和创建Java字节码的类库。是由东京工业大学的数学和计算机科学系的 Shigeru Chiba &#xff08;千叶 滋&#xff09;所创建的。它已加入了开放源代码JBoss 应用服务器项目,通过使用Javassist对字节码操作为JBoss实现动态AOP框架。javassist是jb…

javassist使用指南

目录 一、快速入门1.1 创建class文件1.2 ClassPool的相关方法1.3 CtClass的相关方法1.4 CtMethod的相关方法1.5 调用生成的类对象1.5.1 通过反射调用1.5.2 通过接口调用 1.6 修改现有的类对象 二、将类冻结三、类搜索路径四、$开头的特殊字符五、ProxyFactory的使用 我们知道Ja…

systemd介绍

由来 Linux 的启动一直采用init进程&#xff0c;这种方法有两个缺点。一是启动时间长。init进程是串行启动&#xff0c;只有前一个进程启动完&#xff0c;才会启动下一个进程&#xff0c;二是启动脚本复杂。init进程只是执行启动脚本&#xff0c;不管其他事情。脚本需要自己处理…

systemd man手册

SYSTEMD&#xff08;1&#xff09;systemd SYSTEMD&#xff08;1&#xff09; 名称 systemd&#xff0c;init-systemd系统和服务管理器 概要 /lib/systemd/systemd [OPTIONS...]init [OPTIONS...] {COMMAND}描述 systemd是Linux操作系统的系统和服务管理器。在启动时作为PID的…

systemd wsl 测试笔记

文章目录 systemd 简介WSL systemdsystemctljournalctlhello serviceSleep 与 Timeout 测试Requires 测试After 测试 systemd 简介 Linux 从关闭到运行, 完整的启动和启动过程有三个主要部分: 硬件启动(Hardware boot): 初始化系统硬件Linux 引导(Linux boot): 加载 Linux 内核…

Linux systemd启动流程

以Ubuntu 18.04.2 LTS为例&#xff0c;列出Systemd启动target中涉及单元(Unit). default.target ( graphical.target by default) graphical.targetRequiresmulti-user.targetWantsdisplay-manager.serviceConflictsrescue.service rescue.targetAftermulti-user.target rescu…

关于 Linux中systemd的一些笔记

写在前面 嗯&#xff0c;准备RHCA&#xff0c;学习整理这部分知识博文内容涉及&#xff1a; systemd简述对于unit的信息的介绍通过systemctl命令控制Service unit的DemoService unit配置文件内容,权值的一些介绍 傍晚时分&#xff0c;你坐在屋檐下&#xff0c;看着天慢慢地黑下…

Linux-Systemd

目录 一、Systemd概述 二、Systemd优势 2.1兼容性 2.2启动速度 2.3systemd 提供按需启动能力 2.4采用 linux 的 cgroups 跟踪和管理进程的生命周期 2.5启动挂载点和自动挂载的管理 2.6实现事务性依赖关系管理 2.7日志服务 2.8 依赖关系 2.9systemd 事务 三、unit(单…

Systemd 简介

一 概述 Linux 服务管理有两种方式service和systemctl。而systemd是Linux系统最新的初始化系统(init)&#xff0c;作用是提高系统的启动速度&#xff0c;尽可能启动较少的进程&#xff0c;尽可能更多进程并发启动&#xff0c;systemd对应的进程管理命令就是systemctl。值得一提…

systemd简介

Systemd 是一个专用于 Linux 操作系统的系统与服务管理器,其目的是要取代Unix时代以来一直在使用的init系统。 systemd概述Systemd 是 Linux 系统中最新的初始化系统(init),它主要的设计目标是克服 sysvinit 固有的缺点,提高系统的启动速度。 systemd框架图 根据 Linux 惯…

Systemd 入门及常用命令

目录 Systemdsystemd架构systemd 系统管理管理系统查看启动耗时查看当前主机的信息 Unit 资源查看当前系统的所有 Unit查看系统状态和单个 Unit 的状态 Unit 管理依赖关系Unit 配置文件查看配置文件的内容 Targettarget&#xff08;Systemd&#xff09; 与 runlevel&#xff08…

systemd 介绍

转自&#xff1a;https://www.linuxidc.com/Linux/2018-03/151291.htm 从 init 系统说起 Linux 操作系统的启动首先从 BIOS 开始&#xff0c;接下来进入 boot loader&#xff0c;由 bootloader 载入内核&#xff0c;进行内核初始化。内核初始化的最后一步就是启动 PID 为 1 的 …