ByteBuddy 实战 1 生成一个类

304 阅读2分钟

简介

Byte Buddy 是一个用于 Java 的强大库,专注于在运行时生成 Java 类和字节码操作。它提供了一种简单而灵活的方式来创建、修改和操作 Java 类,而无需直接处理复杂的字节码。
maven坐标

<dependency>
    <groupId>net.bytebuddy</groupId>
    <artifactId>byte-buddy-agent</artifactId>
    <version>1.12.10</version>
</dependency>

1、创建一个类

1.1、code

private String path;
@Before
public void init(){
    path = ByteBuddyTest.class.getClassLoader().getResource("").getPath();
}
@Test
public void makeClassTest() throws IOException {
    DynamicType.Unloaded<Object> unloaded = new ByteBuddy()
            .subclass(Object.class) // 继承自 Object 类
            .make();// 创建类型
    unloaded.saveIn(new File(path)); //把生成的类放到指定目录 
}

代码块1

2、生成列的命名规则

Byte Buddy 提供了灵活的命名策略(NamingStrategy),用于动态生成类时确定类名。命名策略可以帮助确保生成的类名是唯一的,并且符合项目的命名约定。以下是 Byte Buddy 中命名策略的一些关键点和常见用法:
2.1、默认命名策略
Byte Buddy 默认使用的命名策略是 NamingStrategy.SuffixingRandom。这个策略会在给定的基础名称后附加一个随机的后缀,以确保类名的唯一性。默认情况下,生成的类名格式如下:

<基础名称>$ByteBuddy$<随机后缀>

不指定命名策略的情况下代码块1生成的类名:
1、对于父类是jdk自带类情况:net.bytebuddy.renamed.java.lang.ObjectByteBuddyByteBuddyTWz5yREQ
2、对于父类非jdk自带类的情况:com.roadjava.bytebuddy.UserManagerByteBuddyByteBuddyKa6rHJuN 指定命名策略的情况下代码块1生成的类名:
1、对于父类是jdk自带类情况:net.bytebuddy.renamed.java.lang.ObjectroadjavaroadjavaawfkGHLm 2、对于父类非jdk自带类的情况:com.roadjava.bytebuddy.UserManagerroadjavaroadjavakjf1sfxL 代码如下:

@Test
public void makeClassTest() throws IOException {
   //默认策略
    NamingStrategy.SuffixingRandom roadjava = new NamingStrategy.SuffixingRandom("roadjava");
    DynamicType.Unloaded<Object> unloaded = new ByteBuddy()
            .with(roadjava)
            .subclass(Object.class) // 继承自 Object 类
            .make();// 创建类型
    unloaded.saveIn(new File(path));
}

2.2、指定生成类的名字

@Test
public void makeClassTest() throws IOException {
    NamingStrategy.SuffixingRandom roadjava = new NamingStrategy.SuffixingRandom("roadjava");
    DynamicType.Unloaded<Object> unloaded = new ByteBuddy()
            .with(roadjava)
            .subclass(Object.class) // 继承自 Object 类
            .name("com.example.DynamicGeneratedClass") // 指定类名
            .make();// 创建类型
    unloaded.saveIn(new File(path));
}

生成的类名称: com.example.DynamicGeneratedClass

3、字节码作为文件输出到指定位置

@Test
public void makeClassTest() throws IOException {
    DynamicType.Unloaded<Object> unloaded = new ByteBuddy()
            .subclass(Object.class) // 继承自 Object 类
            .name("com.example.DynamicGeneratedClass") // 指定类名
            .make();// 创建类型
    //获取字节码文件并写到指定的文件内
    byte[] bytes = unloaded.getBytes();
    FileUtils.writeByteArrayToFile(new File("/a/a.class"), bytes);
    //把生成的字节码保存到指定目录
    unloaded.saveIn(new File(path));
    //把生成的字节码直接注入到某个jar包内
    unloaded.inject(new File("/a/a.jar"));
}

下一篇# ByteBuddy 实战 2 实例方法插桩

参考:# bytebuddy核心教程