使用 Byte Buddy 运行时生成泛型子类

在上一篇中尝试了 使用 Javassist 运行时生成泛型子类,这里要用另一个更方便的字节码增加组件 Byte Buddy 来实现类似的功能, 但代码上要直白一些。就是运用 Byte Buddy 在运行时生成一个类的子类,带泛型的,给类加上一个注解,可生成类文件或 Class 实例,不过这里更进一步,实现的方法是带参数的。

用 Byte Buddy 操作起来更简单,根本不需要接触任何字节码相关的,诸如常量池等概念。与 Javassist 相比,Byte Buddy 更为先进的是能生成的类文件都是可加载运行的,不像 Javassist 生成的类文件反编译出来是看起来是正常的,但一加载执行却不那回事。

本例所使用的 Byte Buddy 的版本是当前最新的 1.6.7,在 Maven 项目中用下面的方式引入依赖

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

下面是几个需要在本例中用到的类定义

泛型的 Repository 类

与前面有所不同的是上面的抽象方法带有一个参数

注解 Scope

测试代码如下

请从运行输出结果与上面的注释中去理解操作过程。

上面的实现与 使用 Javassist 运行时生成泛型子类 相比要简洁了许多:

  1. 其中子类中默认构造调用父类默认构造的情况不需要特别说明
  2. 给泛型指定参数类型也不容易产生问题
  3. 给类加个注解也无需涉到了常量池的概念
  4. 并且泛型方法无须关心类型擦除的机制, 这一点可对比两篇中生成的字节码反编译出的 findOne() 方法返回类型, Object v.s. String

控制台的输出为

Feb 01, 2017 10:32:30 PM net.bytebuddy.dynamic.DynamicType$Default saveIn
INFO: Writing file to existing folder structure: target/classes/cc/unmi
Session
http://yanbin.blog/?p=7792

不妨看看生成的 target/classes/cc/unmi/UserRepository.class 文件在 IntelliJ IDEA 中反编译后的样子

应用拓展可参考前一篇 使用 Javassist 运行时生成泛型子类 的末尾部分

在搜索关于 Byte Buddy 使用疑问时常常可以看到作者 Rafael Winterhalter 本人热心解答。

相关链接:

  1. Byte Buddy 官方指南
  2. Easily Create Java Agents with Byte Buddy

本文链接 https://yanbin.blog/leverage-bytebuddy-generate-generic-subclass/, 来自 隔叶黄莺 Yanbin Blog

[版权声明] Creative Commons License 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。

Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments