分类: 高性能计算
2023-01-29 10:20:42
作者:京东物流 王北永 姚再毅
日常开发过程中,尤其在DDD过程中,经常遇到VO/MODEL/PO等领域模型的相互转换。此时我们会一个字段一个字段进行set|get设置。要么使用工具类进行暴力的属性拷贝,在这个暴力属性拷贝过程中好的工具更能提高程序的运行效率,反之引起性能低下、隐藏细节设置OOM等极端情况出现。
本扩展组件基于mapstruct进行扩展,简单介绍mapstruct实现原理。
mapstruct是基于JSR 269实现的,JSR 269是JDK引进的一种规范。有了它,能够实现在编译期处理注解,并且读取、修改和添加抽象语法树中的内容。JSR 269使用Annotation Processor在编译期间处理注解,Annotation Processor相当于编译器的一种插件,因此又称为插入式注解处理。
我们知道,java的类加载机制是需要通过编译期运行期。如下图所示
mapstruct正是在上面的编译期编译源码的过程中,通过修改语法树二次生成字节码,如下图所示
以上大概可以概括如下几个步骤:
1、生成抽象语法树。Java编译器对Java源码进行编译,生成抽象语法树(Abstract Syntax Tree,AST)。
2、调用实现了JSR 269 API的程序。只要程序实现了JSR 269 API,就会在编译期间调用实现的注解处理器。
3、修改抽象语法树。在实现JSR 269 API的程序中,可以修改抽象语法树,插入自己的实现逻辑。
4、生成字节码。修改完抽象语法树后,Java编译器会生成修改后的抽象语法树对应的字节码文件件。
从mapstruct实现原理来看,我们发现mapstruct属性转换逻辑清晰,具备良好的扩展性,问题是需要单独写一层转换接口或者添加一个转换方法。能否将转换接口或者方法做到自动扩展呢?
上面所说mapstruct方案,有个弊端。就是如果有新的领域模型转换,我们不得不手动写一层转换接口,如果出现A/B两个模型互转,一般需定义四个方法:A->B、B->A、List