bytebuddy的开发指南-翻译
bytebuddy的开发指南-翻译
翻译这个的⽬的是,简述了源码的结构
⼊门
⾸先,您需要在本地计算机上创建Byte Buddy的副本。克隆存储库后,您可以使⽤Maven构建项⽬ 。你的shell命令,这可能看起来像这样:
git clone github/raphw/byte-buddy.git
cd byte-buddy
mvn package
在开始编码之前,请确保所有测试⽤例都能成功运⾏。Byte Buddy的分⽀⼀直都是这种情况。我们当前的版本可以肯定地证实了这⼀点 ,该版本在监测Byte Buddy的最新状态。Travis被设置为针对v6 和 v7以及 v6 和 v7来编译和测试项⽬ 。由于我们某些测试是创建和加载Java类,因此要确保所⽣成类的格式
能被特定Java版本能够解析。如果您要对Byte Buddy进⾏更改并且会直接影响所⽣成的字节码,请在提交更改之前确保使⽤不同的Java版本充分测试您的更改。这些都意味着您需要编写与Java 6编译器兼容的Java代码。通常,您的代码应⾄少具有90%的测试覆盖率,但是与只尝试碰到任何⾏的测试相⽐,我们推荐进⾏彻底(100%)的测试。您可以随时运⾏Maven
的cobertura:cobertura来获取覆盖率。Byte Buddy当前的测试覆盖率是85%。作为更现代的替代⽅法,Byte Buddy还⽀持通过从Maven
运⾏变异测试org.pitest:pitest-maven:mutationCoverage 。但是请记住,与计算覆盖率相⽐,运⾏变异测试需要⼤量额外的运⾏时间。最后,可以激活Maven 的integration profile 配置⽂件,以扫描代码库中潜在的错误。这个配置⽂件是始终在持续集成服务器上激活的。 另⼀⽅⾯,checks profile聚集了运⾏速度更快的代码检查,并且对于任何Maven构建默认情况下都被激活。
该项⽬分为不同的模块。
根项⽬byte-buddy-parent是任何Byte Buddy模块配置的共同基础。
项⽬的实现代码在byte-buddy-dev模块。该模块是直接依赖ASM库,因此dev作为模块的名字。
由于ASM库·不能保证向后兼容性·,因此byte-buddy模块负责将ASM依赖关系重新打包到Byte Buddy
⾃⼰的名称空间中。这样做会将ASM依赖(shift)重命名为net.bytebuddy.jar.asm。这个dependency-free⽆依赖的模块没有定义其⾃⾝的来源,⽽是依赖于byte-buddy-dev模块。在其构建过程中,将解决所有依赖性并创建dependency-free部署描述符。更多的说明在。为了重新打包,您需要使⽤extras profile配置⽂件运⾏Maven构建,这将进⼀步触发源代码的构建和javadoc的⽣成。如果gpg Maven尝试为所有产出签名。为了实现这⼀点, 签名者必须正确配置gpg插件。
android编程入门指南 pdf作为另⼀个模块,byte-buddy-benchmark包含⼀个 基准测试,,⽤于测量Byte Buddy的运⾏时的耗时与性能,来和与其他代码⽣成库相⽐。
byte-buddy-agent该模块提供了⼀个Java代理,该代理可以增强Byte Buddy的通⽤API。
byte-buddy-android模块包含⼀个在Android平台上起作⽤的ClassLoadingStrategy,其中 byte-buddy-android-test模块定义了⼀个应⽤此策略的测试应⽤程序。这仅当android profile配置⽂件被激活时才构建它,因为构建模块需要Android SDK。
架构概览
每个代码⽣成框架都需要⼀种反映类型及其成员的⽅法。Byte Buddy通过TypeDescription接⼝访问类型信息。该接⼝提供的API 和Java反射API 中定义的Class相似,并且可以使⽤TypeDescription.ForLo
adedType来代表加载过的类,这个会包括具体的类型。但是,Byte Buddy 也可以⽤于创建Java agent,在该Java agent中,需要在加载类之前对类进⾏操作。因此,Byte Buddy永远不会对已经加载过的类型进⾏操作。所有描述类型接⼝都在net.bytebuddy.description包中到。
同样,Byte Buddy将泛型描述为·ypeDescription.Generic接⼝的实例。该接⼝⽐Java⾃⾝的等效接⼝(TypeByte Buddy的Type接⼝,提供了⽤于处理各种通⽤类型的⽅法)丰富。当使⽤泛型的⼀些不⽀持的功能时将引发异常。我们选择这种⽅法作为Java语⾔所需的类型转换⽅法更简介的替代。由于⼤多数操作是由visitors(asm访问字节码的接⼝)执⾏的,因此实际上这并不是问题。
Byte Buddy建⽴在ASM字节代码解析器之上,该解析器已成为Java⽣态系统中字节代码解析的事实上的标准。ASM的 接⼝来操作字节码的⽣成,通常是使⽤代表名称和描述符的字符串值来(所以很简单)。Byte Buddy提供了⼀个StackManipulation 接⼝来封装了visitors的命
令,StackManipulation ⽤来和Byte Buddy 的 descriptio 接⼝交互,把需要的的值提取为适当的格式并与ASM进⾏交互。此外,每种堆栈操作都知道其对JVM操作数堆栈⼤⼩的影响。这样,就可以将⼏种堆栈操作组合在⼀起,以计算它们对最⼩堆栈⼤⼩的共同要求。可以⽤⼀个ByteCodeAppender 来表⽰⼏种堆栈操作的。字节码追加器代表⼀个代码块,并且需要将操作数堆栈留空。另外,字节代码追加器应该暴露为本地变量(local variables 就是字节码知识⾥⾯的本地变量,)的空间(执⾏字节码
指令时,需要关联使⽤这些变量)。通常,字节码追加器由⼀个或多个堆栈操作组成。与代码⽣成相关的所有类都收集在net.bytebuddy.implementation.bytecode包中。
每个字节码附加器以接受⽅法的实现作为⼊参,然后apply到⽬标⽅法上。此外,它还接收⼀个ASM visitor ,⽤于注册该⽅法的代码和的实例 Implementation.Context。Implementation.Context允许注册辅助类型(auxiliary type)。辅助类型表⽰执⾏该⽅法所需的帮助程序类型(就是额外的⼯具类,以便于其他操作)。⽐如,⼀个代理类要调⽤被修改过的类中的⽅法。通常会使⽤MethodDelegation为被修改过的类加⼀
个@SuperCall注解。Implementation.Context是Byte Buddy中为数不多的可变类之⼀,因为它伴随着的ASM 的method visitor 本事就是可变得(这⾥的变是指动态⽣成,⽣成时依赖条件)。但是,由于Implementation.Context并未公开给公共API,因此也不应该
由ByteCodeAppender 也不应该暴露Implementation.Context给⽤户使⽤。
构造⽅法的top-level的API是Implementation接⼝。⼀个ByteCodeAppender,需要⼀个Implementation的是例给出⼀个instrumented type。此外,Implementation可以⽤来注册额外的⽅法,字段或代码块,在instrumented type静态初始化化的时候。最后,任何实现实例都会收到⼀个实例Implementation.Target,它提供了⼀种访问instrumented type中属性的⽅法,该属性与具体的类型⽆
关。例如,可以查询instrumented type的 super⽅法 调⽤。如果⽤户执⾏subclass的⽣成,则此查询将返回真正super⽅法的。如果⽤户进⾏type-rebasement,,则实现⽬标实现将调⽤被重新创建⽅法的原始代码(原始代码的⽅法被重命名,然后被放在新⽅法中)。
在Byte Buddy中,通过将属性注册到可以构造任何类型DynamicType.Builder。builder 本⾝构造了⼀个InstrumentedType实例,该实例可以扩展 TypeDescription以允许Byte Buddy的其他组件在创建其类型之前查看之前的的类型。此外,⽅法和字段实现以FieldRegistry或 ⽅式注册MethodRegistry。最后,动态类型构建器将所有收集的信息TypeWriter提供给与ASM API交互以⽣成类⽂件的所有类型,并将其应⽤于匹配的⽅法描述 。
编码约定
Byte Buddy的⽬标是实现完全不变,除了与⼤多数易变的ASM库进⾏交互的易变类之外。但是,可变组件必须隔离在与ASM交互的范围内,并且不得暴露给最终⽤户。此类实例也不应存储为字段的值。此外,某些组件(例如Byte Buddy的类加载器)由于其作为类加载器的性质⽽可变。但是,应将Byte Buddy中的所有集合视为不可变的,并且当从公共API返回集合时,也必须强制执⾏此属性。
所有⼀成不变的类必须实现适当的hashCode,并equals为对象平等是⼀些Byte Buddy组件的⼀个重要概念,⽅法。例如,任
何Implementation实例都必须仅⼀次性准备instrumented type 类型,因为在Java中两次注册具有相同名称的字段是不合法的。为确保这⼀点,Implementation将检查任何对象是否与之前有机会准备插⼊类型的实现是否相等。如果实现内部依赖于不同的对象,则所有这些组件都必须履⾏其相等的约束,这⼀点很重要。另外,任何组件都应实施适当的 toString⼀种改进调试的⽅法,尤其是在帮助论坛上发布了⽤户的堆栈跟踪信息时。使⽤ObjectPropertyAssertion,Byte Buddy可以运⾏单元测试来确定所有这些⽅法的正确实现。
Byte Buddy是强⾯向对象,但从⾯向函数设计上获得了⼀些启发。不幸的是,作为许多其他库开发⼈员使⽤的元库,Byte Buddy受到强⼤的兼容性要求的约束,并在Java 6上进⾏编译。为模仿函数,Byte Buddy经常通过枚举实现接⼝,其中枚举产⽣命名函数。最后,类⽂件被⽤作相关类的容器⽽不是包。在类⽂件中,可以定义⽐top-level类更好的可见性范围,例如通过允许protected只能由⼦类或在内部使⽤另⼀个类的类中看到的类。同样,当重构后不再需要⼀个类时,此分组约定使删除所有相关代码变得容易。
作为元库,Byte Buddy试图提供对API尽可能开放的API,因为⽆法预期使⽤范围。只要有可能,委托将是优于类扩展的⾸选扩展机制。所有代码都应记录在案,这使得此属性 更易于通过⾃动检查进⾏验证。在Byte Buddy中,将其null⽤作字段,参数的值或⽅法返回值是⼀种不好的做法。模仿Java反射API的描述类型是⼀个例外,其中null值是常见的。由于描述实例(description instances)向最终⽤户公
开,因此决定将相似性视为⽐⼀致性更重要的因素。所以潜在的null值必须记录在⽅法上。对于Byte Buddy,未检查的异常⽐检查的异常更可取。
贡献
修复错误后,只需 在GitHub上创建拉取请求即可。收到通知后,我们将尽快调查此事。但是,请确保已正确描述了更改和已解决的问题,并提供了⼀个可重现该问题并证明您的修复程序有效的测试⽤例。这使我们的⼯作更加轻松,我们将能够更快地应⽤您的补丁。如果添加新的⽅法,字段或类型,请确保编写⼀些描述其⽤途的代码内⽂档。如果您应⽤与性能相关的更改,请使⽤byte-buddy-benchmark套件。最后,请注意,Byte Buddy的新版本通常是在其⾃⼰的分⽀中开发的。
如果您要提供功能,请先,然后再花费⼤量时间,以便我们可以讨论您的更改在Byte Buddy当前的开发状态下如何有意义。字节伙伴旨在稳定地提供更多功能,但我们不会以其稳定性和代码⼀致性为代价来扩展其功能集。但是,不要因本公告⽽⽓disc。如果您对Byte Buddy的源代码有⾜够的了解,能够实现您想要共享的新功能,那么您肯定会考虑⼀下,我们将尽最⼤努⼒将其合并到我们的版本中!只需与我们交谈,我们⾮常乐意欢迎您加⼊我们。
如果您想为Byte Buddy的⽂档,本⽹页上的描述甚⾄本⽹页的结构和设计做出贡献,绝对欢迎您这样做!我们深信,透彻和最新的⽂档是成功项⽬的关键,我们将尽最⼤努⼒实现这⼀信念。只要可以改
善Byte Buddy的可访问性或外观,甚⾄可以进⾏很⼩的更改,因为最终,该项⽬是为⽤户设计的。只需克隆此⽹页,该⽹页托管在项⽬gh-pages分⽀的GitHub上。该⽹页是使⽤angular.js和 Twitter的Bootstrap创建的。
路线图
Byte Buddy已达到1.0版,除了尚不⽀持的两个功能外,还被认为是功能完整。随着1.0版的发布,库的稳定性和性能得到了极⼤的重视,并且防御性地增加了新功能。⾃然,Java编程语⾔和字节代码格式的发展将在未来需要较新的版本,⽽Byte Buddy的⽬标是提供⼀种向后兼容的⽅式来处理旧版本和较新版本的Java。Java 9⽀持⽬前仍处于试验阶段。从Java 8开始,Byte Buddy当前不⽀持以下功能:
类型推断
Java编译器可以推断泛型类型。字节好友当前不提供此类功能。对类型推断的⽀持将允许更好地验证泛型类型并实现Assigner考虑泛型类型信息的。不幸的是,此功能在实际应⽤很少的情况下需要进⾏⼤量⼯作。因此,⽬前尚未实现。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。