jooq
欢迎来到jOOQ Tuesdays系列。 在本系列文章中,我们每隔一个月的第三个星期二发布一篇文章,从jOOQ的角度采访我们发现该行业令人兴奋的人。 这包括从事SQL,Java,开放源代码以及各种其他相关主题的人员。
我们很高兴在第七版中与Rafael Winterhalter进行交谈,他将向我们介绍Java字节代码的深度以及他的库Byte Buddy,该库使使用字节码的工作变得非常容易 。
请注意,Byte Buddy赢得了2015年“杜克选择奖” -对此我们表示祝贺!
字节好友的作用是什么?
字节伙伴是一个代码生成和操作库。 它提供了API,用于在运行时创建新的Java类以及在加载之前或之后更改现有的类。
乍一看,这听起来似乎很深奥,但是运行时代码生成已在许多Java项目中使用。 库开发人员通常使用代码生成工具来实现面向方面的编程。 例如, 模拟库Mockito使用Byte Buddy在运行时创建模拟类的子类。 为了实现模拟,Mockito会覆盖类的所有方法,以便在测试中调用某个方法时,不会调用用户的原始代码。 还有许多其他知名的代码生成用户。 例如,Spring使用代码生成来实现其注释方面,例如安全性或事务。 而且,Hibernate使用代码生成通过覆盖那些getter来延迟从getter方法中加载属性,以仅在调用它们时才查询数据库。
当有诸如ASM,CGLIB,AspectJ或Javassist之类的替代方案时,为什么需要Byte Buddy?
在开始从事Byte Buddy的工作之前,我曾作为贡献者参与了其他几个开源项目。 如前所述,代码生成是实现许多库的典型要求,因此我习惯了使用CGLIB和Javassist 。 但是,我对这些库的局限性不断感到沮丧,我想解决我发现的问题。 最终,我开始写一个替代库,后来以Byte Buddy的形式发布。
要了解替代库的局限性,模拟是一个很好的示例用例。 Mockito中的小样以前是使用CGLIB创建的。 CGLIB是一个相当成熟的库。 它已经存在了15年以上,当它最初被开发时,图书馆的开发人员当然并没有想到诸如注释,通用类型或防御方法之类的功能。 但是,注释确实成为许多不接受模拟实例的API的重要组成部分,因为所有重写方法的注释都会丢失。 在Java中,方法的注释在被覆盖时永远不会继承。 并且类型的注释只有在明确声明为时才继承。 为了克服这个问题,Byte Buddy允许将任何注释复制到子类中,该子类现在是Mockito 2中的功能。
相反,Javassist允许复制注释,但我个人不喜欢该库的方法。 在Javassist中,所有生成的代码都表示为包含在字符串中的Java代码。 结果,Javassist代码的结构类似于非结构化的Java代码,后者仅将SQL描述为级联字符串。 除了创建难以维护的代码外,此方法还提供了漏洞,例如类似于SQL注入的Java代码注入。 有时可以通过允许Javassist代码编译任意代码来攻击Javassist代码,这可能会对应用程序造成严重损害。
在处理现有代码时, AspectJ是一个功能强大的工具。 但是,通过Byte Buddy,您可以用普通的简单Java来执行AspectJ能够执行的任何操作。 这样,开发人员无需学习新的语法或编程隐喻,也无需为其构建过程和IDE安装工具。 此外,我认为连接点和切入点术语并不直观,因此决定完全避免使用。 相反,我决定模仿开发人员已经从Java编程语言中了解的术语,以简化Byte Buddy的第一步。
另一方面, ASM是实现Byte Buddy的基础。 ASM是字节代码解析器,而不是代码生成库。 ASM处理单个类文件,并且不考虑类型层次结构。 ASM既没有类加载的概念,也没有在字节码指令之上包括更高级别的概念。 但是,Byte Buddy提供了一个适配器,该适配器向需要生成非常特定的代码的用户公开ASM API。
如何参与低级Java?
一开始,我为自己设定了仅创建具有注释支持的CGLIB版本的目标,这正是我最初需要的。 但是我很快发现,许多开发人员正在寻找Byte Buddy如今已成为的解决方案。 因此,我开始计划使Java虚拟机的完整功能集可访问。 为此,学习类文件格式的所有细节和极端情况已成为实现这些功能的必要条件。 公平地讲,一旦掌握了类文件格式,它就显得微不足道了,我真的很高兴看到我的库成熟。
您最感觉到家在哪里?
我想为正确的工作使用正确的工具。 显然,我喜欢使用字节码,但是在生产项目中工作时,我会避免手工制作字节码。 最后,这是诸如Byte Buddy之类的更高级抽象的目的。
从常见的用例来看,但是Byte Buddy通常用于通过基于方法的注释更改代码来实现自定义功能。 从某种意义上说,Byte Buddy使开发人员能够实现自己的4G抽象。 声明式编程是某些任务的绝佳抽象,SQL是其中之一。
作为网红,您最激动人心的故事是什么?
主要是,我很高兴认识我的图书馆用户。 我遇到了一些与大型团队一起实施基于我的软件的内部框架的人,很显然,让Byte Buddy证明如此有用使我感到骄傲。
非常感谢拉斐尔
如果您想了解有关Rafael的工作,字节码或Byte Buddy的更多信息 ,请查看他在JavaZone上的演讲:
翻译自: https://www.javacodegeeks.com/2015/12/jooq-tuesdays-rafael-winterhalter-wrestling-byte-code-byte-buddy.html
jooq