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());
}

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

嘻嘻,是不是还有点意思

相关推荐
VX:Fegn08953 小时前
计算机毕业设计|基于ssm + vue超市管理系统(源码+数据库+文档)
前端·数据库·vue.js·spring boot·后端·课程设计
Java天梯之路7 小时前
Spring Boot 钩子全集实战(七):BeanFactoryPostProcessor详解
java·spring boot·后端
wr2005148 小时前
第二次作业,渗透
java·后端·spring
短剑重铸之日8 小时前
《SpringCloud实用版》生产部署:Docker + Kubernetes + GraalVM 原生镜像 完整方案
后端·spring cloud·docker·kubernetes·graalvm
爬山算法8 小时前
Hibernate(67)如何在云环境中使用Hibernate?
java·后端·hibernate
女王大人万岁9 小时前
Go标准库 io与os库详解
服务器·开发语言·后端·golang
露天赏雪9 小时前
Java 高并发编程实战:从线程池到分布式锁,解决生产环境并发问题
java·开发语言·spring boot·分布式·后端·mysql
短剑重铸之日10 小时前
《SpringCloud实用版》 Seata 分布式事务实战:AT / TCC / Saga /XA
后端·spring·spring cloud·seata·分布式事务
FAFU_kyp10 小时前
RISC0_ZERO项目在macOs上生成链上证明避坑
开发语言·后端·学习·macos·rust
qq_124987075310 小时前
基于springboot的会议室预订系统设计与实现(源码+论文+部署+安装)
java·vue.js·spring boot·后端·信息可视化·毕业设计·计算机毕业设计