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

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

嘻嘻,是不是还有点意思

相关推荐
摸鱼仙人~19 分钟前
Spring Boot + MyBatis 实现的简单用户管理项目的完整目录结构示例
spring boot·后端·mybatis
Victor35621 分钟前
MySQL(52)如何使用EXPLAIN分析查询性能?
后端
用户05956611920924 分钟前
现代应用中 Java 集合框架的核心技术与实践解析
java·后端
L2ncE30 分钟前
ES101系列09 | 运维、监控与性能优化
后端
CRMEB定制开发1 小时前
PHP 支付系统扩展实战:从微信 / 支付宝到银联的多驱动架构设计
后端
史文豪1 小时前
nacos2.5.1版本基于docker的自定义部署(适配人大金仓)
后端
aiopencode1 小时前
移动端抓包指南:为什么真机HTTPS总是抓不到?(多工具对比 + Sniffmaster实战)
后端
追逐时光者1 小时前
一款 .NET 开源、免费的适用于 Windows 下 PC 版微信/QQ/TIM的防撤回补丁(我已经看到了,撤回也没用了)!!
后端·.net
IT_陈寒1 小时前
开发者必看!5个VSCode隐藏技巧让你的编码效率提升200% 🚀
前端·人工智能·后端
保持学习ing1 小时前
黑马Java面试笔记之 微服务篇(SpringCloud)
java·笔记·后端·阿里云·面试·负载均衡·springcloud