ByteBuddy学习(1)

ByteBuddy是什么?

ByteBuddy 是一个功能强大的 Java 字节码操作库,主要用于在运行时动态生成和修改 Java 类。它提供了一种简单易用的 API,使得开发者无需直接操作复杂的字节码指令,即可实现动态代理、AOP(面向切面编程)、类增强等功能。 官网地址

快速使用

引入依赖

xml 复制代码
<dependency>
    <groupId>net.bytebuddy</groupId>
    <artifactId>byte-buddy</artifactId>
    <version>LATEST</version>
</dependency>

新建一个类

java 复制代码
public void helloWrold(){
    try {
        // 创建动态类
        Class<?> dynamicType = new ByteBuddy()
               .subclass(Object.class)
               .method(ElementMatchers.named("toString"))
               .intercept(FixedValue.value("Hello World"))
               .make()
               .load(ByteByddyTest.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
               .getLoaded();

        // 使用构造函数创建实例
        Constructor<?> constructor = dynamicType.getConstructor();
        Object instance = constructor.newInstance();

        // 调用 toString 方法
        String helloworld = instance.toString();
        System.out.println(helloworld);
    } catch (Exception e) {
        e.printStackTrace();
    }
}
  • new ByteBuddy():创建一个 ByteBuddy 实例,作为构建动态类的起点。
  • .subclass(Object.class):指定要创建的动态类是 Object 类的子类。
  • .method(ElementMatchers.named("toString")):使用 ElementMatchers.named 方法匹配器选择 toString 方法,即要对这个方法进行拦截和修改。
  • .intercept(FixedValue.value("Hello World")):指定拦截逻辑,使用 FixedValue 让被拦截的 toString 方法重写,不使用默认的Object#toString方法,而是始终返回 "Hello World"字符串。
  • .make():根据前面的配置生成字节码。
  • .load(ByteBuddyExample.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER):使用当前类 ByteBuddyExample 的类加载器,并采用 ClassLoadingStrategy.Default.WRAPPER 策略将生成的字节码加载到 JVM 中。
  • .getLoaded():获取加载后的 Class 对象,存储在 dynamicType 变量中。
  • dynamicType.getConstructor():通过反射获取动态类的无参构造函数。
  • constructor.newInstance():调用构造函数创建动态类的一个新实例,存储在 instance 变量中。
  • instance.toString():调用动态类实例的 toString 方法,由于前面已经对该方法进行了拦截和重写,所以会返回 "Hello World"
  • System.out.println(helloworld):将 toString 方法的返回值打印到控制台

小测试

你可以将ElementMatchers.named("toString")中的toString 改为tostring,试试,会发现到最后就不能正常输出了,输入的是这个 原因是因为由于 ElementMatchers.named("tostring") 要匹配的就是'Object'类下面的'toString'方法,由于大小写不一致导致没有匹配到,但是 instance 变量的 toString() 方法没有被拦截,仍然会使用 Object 类的默认 toString() 实现,输出的是对象的哈希码字符串,而不是 "Hello World"

如果你不知道Object类的默认toString实现,没关系,实际上sout输出的一个对象的时候就会默认区调用这个对象的toString方法,而Object的默认toString方法是这样实现的

java 复制代码
public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

所以最后输出的是一个这样的格式的结果

嘻嘻,是不是还有点意思

相关推荐
永远不会的CC2 小时前
浙江华昱欣实习(4月23日~ 4月19日)
后端·学习
直奔標竿3 小时前
Java开发者AI转型第二十五课!Spring AI 个人知识库实战(四)——RAG来源追溯落地,拒绝AI幻觉
java·开发语言·人工智能·spring boot·后端·spring
嘟嘟MD3 小时前
程序员副业 | 2026年4月复盘
后端·创业
时空系3 小时前
认识Rust——我的第一个程序 Rust中文编程
开发语言·后端·rust
DevilSeagull3 小时前
Windows 批处理 (Batch) 编程: 从入门到入土. (一) 基础概念与环境配置
开发语言·windows·后端·batch·语言
CAE虚拟与现实4 小时前
五一假期闲来无事,来个前段、后端的说明吧
前端·后端·vtk·three.js·前后端
0xDevNull4 小时前
Java泛型详解
java·开发语言·后端
yeeanna4 小时前
GO函数的特殊性
开发语言·后端·golang
时空系4 小时前
第6篇:数据容器——管理大量数据 Rust中文编程
开发语言·后端·rust
eLIN TECE4 小时前
Go基础之环境搭建
开发语言·后端·golang