简介
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.ObjectTWz5yREQ
2、对于父类非jdk自带类的情况:com.roadjava.bytebuddy.UserManagerKa6rHJuN
指定命名策略的情况下代码块1生成的类名:
1、对于父类是jdk自带类情况:net.bytebuddy.renamed.java.lang.ObjectawfkGHLm
2、对于父类非jdk自带类的情况:com.roadjava.bytebuddy.UserManagerkjf1sfxL
代码如下:
@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"));
}