常见Bean映射工具分析评测及Orika介绍

原地址:http://tech.dianwoda.com/2017/11/04/gao-xing-neng-te-xing-feng-fu-de-beanying-she-gong-ju-orika/?utm_source=tuicool&utm_medium=referral

Bean映射工具选择

工作中,我们经常需要将对象转换成不同的形式以适应不同的api,或者在不同业务层中传输对象而不同分层的对象存在不同的格式,因此我们需要编写映射代码将对象中的属性值从一种类型转换成另一种类型。

进行这种转换除了手动编写大量的get/set代码,还可以使用一些方便的类库,常用的有apache的BeanUtils,spring的BeanUtils,cglib的BeanCopier

BeanUtils

apache的BeanUtils和spring的BeanUtils中拷贝方法的原理都是先用jdk中 java.beans.Introspector类的getBeanInfo()方法获取对象的属性信息及属性get/set方法,接着使用反射(Methodinvoke(Object obj, Object... args))方法进行赋值。apache支持名称相同但类型不同的属性的转换,spring支持忽略某些属性不进行映射,他们都设置了缓存保存已解析过的BeanInfo信息。

BeanCopier

cglib的BeanCopier采用了不同的方法:它不是利用反射对属性进行赋值,而是直接使用ASM的MethodVisitor直接编写各属性的get/set方法(具体过程可见BeanCopier类的generateClass(ClassVisitor v)方法)生成class文件,然后进行执行。由于是直接生成字节码执行,所以BeanCopier的性能较采用反射的BeanUtils有较大提高,这一点可在后面的测试中看出。

Dozer

使用以上类库虽然可以不用手动编写get/set方法,但是他们都不能对不同名称的对象属性进行映射。在定制化的属性映射方面做得比较好的有Dozer,Dozer支持简单属性映射、复杂类型映射、双向映射、隐式映射以及递归映射。可使用xml或者注解进行映射的配置,支持自动类型转换,使用方便。但Dozer底层是使用reflect包下Field类的set(Object obj, Object value)方法进行属性赋值,执行速度上不是那么理想。

Orika

那么有没有特性丰富,速度又快的Bean映射工具呢,这就是下面要介绍的Orika,Orika是近期在github活跃的项目,底层采用了javassist类库生成Bean映射的字节码,之后直接加载执行生成的字节码文件,因此在速度上比使用反射进行赋值会快很多,下面详细介绍Orika的使用方法。

Orika使用

依赖

<dependency>
    <groupId>ma.glasnost.orika</groupId>
    <artifactId>orika-core</artifactId>
    <version>1.5.2</version><!-- or latest version -->
</dependency>  

简单映射

  1. 构造一个MapperFactory
MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();  

  1. 注册字段映射
mapperFactory.classMap(PersonSource.class, PersonDestination.class)
   .field("firstName", "givenName")
   .field("lastName", "sirName")
   .byDefault()
   .register();

  1. 进行映射
MapperFacade mapper = mapperFactory.getMapperFacade();

PersonSource source = new PersonSource();
// set some field values
...
// map the fields of ‘source‘ onto a new instance of PersonDest
PersonDest destination = mapper.map(source, PersonDest.class);  

在第二步进行的字段映射是双向的,我们可以从目标类型映射回源类型,byDefault()方法用于注册名称相同的属性(如果所有属性名称都相同则可以省略第2步),如果不希望某个字段参与映射,可以使用exclude方法

复杂映射

数组和List的映射

如果在目标类和目的类中分别有下面的属性

class BasicPerson {
  private List<String> nameParts;
  // getters/setters omitted
}
class BasicPersonDto {
  private String firstName;
  private String lastName;
  // getters/setters omitted
}

可以使用下面的方式进行映射:

mapperFactory.classMap(BasicPerson.class, BasicPersonDto.class)
   .field("nameParts[0]", "firstName")
   .field("nameParts[1]", "lastName")
   .register();

类类型的映射

class Name {
   private String first;
   private String last;
   private String fullName;
   // getters/setters
}

class BasicPerson {
  private Name name;
  // getters/setters omitted
}
class BasicPersonDto {
  private String firstName;
  // getters/setters omitted
}

使用:

mapperFactory.classMap(BasicPerson.class, BasicPersonDto.class)
   .field("name.first", "firstName")
   .register();

自定义转换器

orika同样支持自定义转换器,将指定类型或指定名称的属性做映射时添加自定义操作,例如,将String类型的或某个属性映射后加一个前缀,或者将Integer类型映射后加1等:

public class MyConverter extends CustomConverter<Date,MyDate> {
   public MyDate convert(Date source, Type<? extends MyDate> destinationType) {
      // return a new instance of destinationType with all properties filled
      //example:source + 1;
   }
}

Date为源类型中要做转换的属性数据类型,例如StringInteger等,MyDate为目标类型中要做转换的属性数据类型。

如果需要定义全局范围的转换:

ConverterFactory converterFactory = mapperFactory.getConverterFactory();
converterFactory.registerConverter(new MyConverter());  

如果仅需要某几个属性使用转换器:

ConverterFactory converterFactory = mapperFactory.getConverterFactory();
converterFactory.registerConverter("myConverterIdValue", new MyConverter());

mapperFactory.classMap( Source.class, Destination.class )
   .fieldMap("sourceField1", "sourceField2").converter("myConverterIdValue").add()
   ...
   .register();

其他说明

  1. Orika支持递归映射,将映射嵌套类直到用“简单”类型完成映射。它还包含故障保险,以正确处理正在尝试映射的对象中的递归引用。
  2. 在于spring集成时,可以将MapperFactory设置为单例

各映射工具的性能测试

构造一个包含普通类型及类类型的Bean对象,使用jmh微基准框架进行测试。由于jvm会对热点代码进行优化:方法反射调用次数超过阈值时会生成一个专用的MethodAccessor实现类,生成其中的invoke()方法的字节码进行执行。

故测试时每种方法先预热执行15次,而后再执行100次获取每次执行的平均时间:

Benchmark                     Mode  Samples   Score  Score error  Units
o.s.MyBenchmark.apache        avgt      100  25.246        0.535  us/op
o.s.MyBenchmark.beanCopier    avgt      100   0.004        0.000  us/op
o.s.MyBenchmark.byHand        avgt      100   0.004        0.000  us/op
o.s.MyBenchmark.dozer         avgt      100   5.855        0.260  us/op
o.s.MyBenchmark.orika         avgt      100   0.353        0.017  us/op
o.s.MyBenchmark.spring        avgt      100   0.627        0.020  us/op  

统计报告中Units单位为微秒/次,由Score项可以看出,基于ASM的cglib BeanCopier拷贝速度基本和手写get/set方法的速度无异,其次的就是基于javassist的Orika了,Orika的速度是spring BeanUtils的两倍,Dozer的20倍,Apache BeanUtils的120倍。

综上,当属性名和属性类型完全相同时使用BeanCopier是最好的选择,当存在属性名称不同或者属性名称相同但属性类型不同的情况时,使用Orika是一种不错的选择。如果你对Orika感到不放心,实际应用前可以写个测试类查看它的转换结果是否符合预期。

原文地址:https://www.cnblogs.com/jpfss/p/10898979.html

时间: 2024-11-09 05:02:10

常见Bean映射工具分析评测及Orika介绍的相关文章

Wireshark(三):应用Wireshark IO图形工具分析数据流

原文出处: EMC中文支持论坛 基本IO Graphs: IO graphs是一个非常好用的工具.基本的Wireshark IO graph会显示抓包文件中的整体流量情况,通常是以每秒为单位(报文数或字节数).默认X轴时间间隔是1秒,Y轴是每一时间间隔的报文数.如果想要查看 每秒bit数或byte数,点击“Unit”,在“Y Axis”下拉列表中选择想要查看的内容.这是一种基本的应用,对于查看流量中的波峰/波谷很有帮助.要进一步查看,点击图形中的任意点就会看到报文的细 节. 为了讲解方便,点击示

对几款网络抓包工具的评测

对几款网络抓包工具的评测 by 拉登哥哥 最近在写个CMD远控 写着写着 想在服务端上做点手脚 都知道杀软误报 特别是黑软大部分都报毒 但实际上是正常的 对此可能部分人并不装杀软 基本上靠自己分析软件是否安全 1 低级点的 用相关工具 检测不能真的完全保证程序无毒  也没啥技术含量 原因是 可能你正在检测时 后门没激活(比如 我设置晚上12点才向外连接等) 你在白天或其它时间检测我的工具 可能没发现任何异常 晚上你开工具做事的时候 后门也跟着激活了 哈哈 这方法 实际中还真有人这么看 以前某个木

几种常见 容器 比较和分析

几种常见 容器 比较和分析 hashmap, map, vector, list ...hash&n list支持快速的插入和删除,但是查找费时; vector支持快速的查找,但是插入费时. map查找的时间复杂度是对数的,这几乎是最快的,hash也是对数的. 如果我自己写,我也会用二叉检索树,它在大部分情况下可以保证对数复杂度,最坏情况是常数复杂度,而std::map在任何情况下都可以保证对数复杂度,原因是它保证存诸结构是完全二叉检索树,但这会在存诸上牺牲一些时间. STL 中的 map 内部

ElasticSearch映射和分析

分析和分析器 分析(analysis)是这样一个过程: 首先,表征化一个文本块为适用于倒排索引单独的词(term) 然后标准化这些词为标准形式,提高它们的"可搜索性"或"查全率" 这个工作是分析器(analyzer)完成的.一个分析器(analyzer)只是一个包装用于将三个功能放到一个包里: 字符过滤器 首先字符串经过字符过滤器(character filter),它们的工作是在表征化(译者注:这个词叫做断词更合适)前处理字符串.字符过滤器能够去除HTML标记,或

Java实体映射工具MapStruct的使用

官网地址:http://mapstruct.org/ MapStruct 是一个代码生成器,简化了不同的 Java Bean 之间映射的处理,所谓的映射指的就是从一个实体变化成一个实体.例如我们在实际开发中,DAO 层的实体(PO)和一些数据传输对象(DTO),大部分属性都是相同的,只有少部分的不同,通过 mapStruct,可以让不同实体之间的转换变的简单.我们只需要按照约定的方式进行配置即可. MapStruct 是一个可以处理注解的 Java 编译器插件,可以在命令行中使用,也可以在 ID

Hibernate复习(七)常见的映射类型B

1.继承关联映射 1.1继承关系映射到多张表 配置: <class name="Product"....> .... <joined-subclass name="" table=""> <key column="t_product_id"/> <property ... /> </joined-subclass> </class> 基本操作:  保存:

端口映射工具:ngrok的使用(可用于本地测试微信)

端口映射工具:ngrok的使用 我们在没有服务器或者上传服务器测试比较麻烦的情况下可以使用ngrok工具,映射本地机器让外网访问,可以用来测试微信哦. 首先下载ngrok 工具: 下载地址是:<a target=_blank href="https://ngrok.com/download">https://ngrok.com/download</a> 然后在ngrok网站注册帐号以得到:Your auth token ,注册地址是:https://ngrok.

微信公众号开发技术基础(二):外网映射工具ngrok的简介和使用

本文结构:(一)用法(二)示例(三)qydev ngrok的下载链接及相关网站 微信公众号开发的时候,微信服务器是需要访问我们的一个公网服务器地址的,但我们又是在本地调试自己的程序的,那怎样让微信服务器能访问到我们本地的服务器呢?那就需要用外网映射工具,将本地IP映射成公网IP,这样就能在公网上访问本地服务了,这里使用ngrok.ngrok原版程序的服务器是在国外的,访问速度极慢或者干脆访问不了,所以这里提供一个服务器搭建在国内的基于ngrok的一个软件:qydev,百度网盘下载链接见文章结尾.

分析评测贴片电容性能的常用方法

首先是贴片电容的四个常规电性能,即容量Cap. 损耗DF,绝缘电阻IR和耐电压DBV,一般地,X7R产品的损耗值DF<=2.5%,越小越好,IR*Cap>500欧*法,BDV>2.5Ur.其次是贴片电容的加速寿命性能,在125deg.c环境温度和2.5Ur直流负载条件下,芯片应能耐100小时不击穿,质量好的可耐1000小时不击穿.再次就是产品的耐热冲击性能,将电容浸入300deg.c锡炉10秒,多做几粒,显微镜下观察是否有表面裂纹,然后可测试容量损耗并与热冲击前对比判别芯片是否内部裂纹.