Orika JavaBean映射工具使用
作者:京东零售 张宾
1.Orika是什么?
Orika是一个简单、快速的JavaBean拷贝框架,它能够递归地将数据从一个JavaBean复制到另一个JavaBean,这在多层应用开发中是非常有用的。
2.为什么要引入Orika?
工作中,我们经常需要将对象转换成不同的形式以适应不同的api,或者在不同业务层中传输对象而不同分层的对象存在不同的格式,因此我们需要编写映射代码将对象中的属性值从一种类型转换成另一种类型。
Orika用于简化多层之间的对象映射,避免苦苦挣扎于手工编码和基于反射的映射。Orika关注尽可能地自动化,同时根据需要提供配置和扩展实现定制。
3.项目常用javabean映射技术
Java反射:性能问题、无法解决嵌套javabean映射复制
手工映射:硬编码、代码量大
序列化方式:通过json、xml的序列化和反序列化方式,字段参数不相同时,需要硬编码赋值
4.常用bean映射工具
BeanUtils:apache的BeanUtils和spring的BeanUtils中拷贝方法的原理都是先用jdk中 java.beans.Introspector类的getBeanInfo()方法获取对象的属性信息及属性get/set方法,接着使用反射(Method的invoke(Object obj, Object... args))方法进行赋值。apache支持名称相同但类型不同的属性的转换,spring支持忽略某些属性不进行映射,他们都设置了缓存保存已解析过的BeanInfo信息。
BeanCopier:cglib的BeanCopier采用了不同的方法:它不是利用反射对属性进行赋值,而是直接使用ASM的MethodVisitor直接编写各属性的get/set方法(具体过程可见BeanCopier类的generateClass(ClassVisitor v)方法)生成class文件,然后进行执行。由于是直接生成字节码执行,所以BeanCopier的性能较采用反射的BeanUtils有较大提高。
Orika:底层采用了javassist类库生成Bean映射的字节码,之后直接加载执行生成的字节码文件,因此在速度上比使用反射进行赋值会快很多。Orika支持递归映射,将映射嵌套类直到用“简单”类型完成映射。它还包含故障保险,以正确处理正在尝试映射的对象中的递归引用。
5.如何使用Orika?
5.1 maven依赖
ma.glasnost.orika
orika-core
1.5.2
5.2 两个javabean字段名称相同映射
MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
//字段名相同映射
mapperFactory.classMap(Person.class, PersonInfo.class).byDefault().register();
MapperFacade mapperFacade = mapperFactory.getMapperFacade();
Person person = new Person();
person.setFirstName("张");
person.setLastName("三");
PersonInfo personInfo = mapperFacade.map(person, PersonInfo.class);
输出结果:

5.3 两个javabean字段名称不相同映射
MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
mapperFactory.classMap(Person.class, PersonDesc.class)
.field("firstName", "givenName").field("lastName", "sirName")
.byDefault() .register();
MapperFacade mapperFacadeDesc = mapperFactory.getMapperFacade();
Person personNew = new Person();
personNew.setFirstName("王");
personNew.setLastName("五");
PersonDesc personDesc = mapperFacadeDesc.map(personNew, PersonDesc.class);
输出结果:

5.4 数组和List映射javabean
public static class PersonNameList {
private List nameList;
public PersonNameList(List nameList) {
this.nameList = nameList;
}
//getter/setter方法
}
mapperFactory.classMap(PersonNameList.class, Person.class)
.field("nameList[0]", "firstName")
.field("nameList[1]", "lastName").register();
List nameParts = Arrays.asList(new String[]{"李", "四"});
Person person = mapperFactory.getMapperFacade().map(new PersonNameList(nameParts), Person.class);
输出结果:

5.5 相同类型javabean复制(原型模式)
MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
mapperFactory.classMap(Person.class, Person.class).byDefault().register();
Person person = new Person();
person.setFirstName("张");
person.setLastName("三");
Person personNew = mapperFactory.getMapperFacade().map(person, Person.class);
输出结果:

5.6 嵌套javabean映射
mapperFactory.classMap(Flight.class, Flight.class).byDefault().register();
Cabin cabinY = new Cabin("Y", "8", 1200);
Cabin cabinF = new Cabin("C", "6", 1900);
Cabin cabinC = new Cabin("F", "A", 2400);
Flight flight = new Flight("CA1831", Lists.newArrayList(cabinY, cabinF, cabinC));
Flight flightCopy = mapperFactory.getMapperFacade().map(flight, Flight.class);
System.out.println("原对象:flight=" + JSON.toJSONString(flight));
System.out.println("新对象:flightCopy=" + JSON.toJSONString(flightCopy));
flightCopy.setFlightNo("MU5183");
flightCopy.getCabins().remove(0);
System.out.println("修改航变号和删除舱位:flightCopy=" + JSON.toJSONString(flightCopy)); System.out.println("原对象:flight=" + JSON.toJSONString(flight));
输出结果:

5.7 List类型映射
MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
mapperFactory.classMap(Cabin.class, CabinDesc.class).byDefault().register();
Cabin cabinY = new Cabin("Y", "8", 1200);
Cabin cabinF = new Cabin("C", "6", 1900);
Cabin cabinC = new Cabin("F", "A", 2400);
List cabinList = Lists.newArrayList(cabinY, cabinF, cabinC);
List cabinDescList = mapperFactory.getMapperFacade().mapAsList(cabinList, CabinDesc.class);
System.out.println("cabinList = " + JSON.toJSONString(cabinList));
System.out.println("cabinDescList = " + JSON.toJSONString(cabinDescList));
输出结果

5.8 自定义数据类型转化器(String to Date)
继承接口CustomConverter类,覆盖实现convert方法
public static class StringToDateConverter extends CustomConverter<String, Date> {
private String dateFormat;
public StringToDateConverter(String dateFormat) {
this.dateFormat = dateFormat;
}
public Date convert(String s, Type<? extends Date> type, MappingContext mappingContext) {
try {
return DateUtils.parseDate(s, dateFormat);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
mapperFactory.getConverterFactory()
.registerConverter(new StringToDateConverter("yyyy-MM-dd"));
mapperFactory.classMap(ArrayMapper.PersonNameList.class, Person.class)
.field("nameList[0]", "firstName").field("nameList[1]", "lastName")
.field("nameList[2]", "birthDate").register();
List nameParts = Arrays.asList(new String[]{"李", "四", "1989-10-11"});
Person person = mapperFactory.getMapperFacade().map(new ArrayMapper.PersonNameList(nameParts), Person.class);
System.out.println("nameParts = " + JSON.toJSONString(nameParts));
System.out.println("person = " + JSON.toJSONStringWithDateFormat(person,"yyyy-MM-dd"));
输出结果:

6. 各映射工具的性能测试
每种方法先预热执行20次,而后再执行100000次获取每次执行的平均时间

7.参考文献
官网:http://orika-mapper.github.io/orika-docs/intro.html
其他:https://www.jianshu.com/p/5daf68dc5758
http://tech.dianwoda.com/2017/11/04/gao-xing-neng-te
-xing-feng-fu-de-beanying-she-gong-ju-orika/
Orika JavaBean映射工具使用的更多相关文章
- 【代码工具】Orika JavaBean映射工具探秘
转自:https://www.cnblogs.com/albert1024/articles/8434741.html Orika是一个简单.快速的JavaBean拷贝框架,Orika使用字节代码生成 ...
- Orika JavaBean映射工具探秘
Orika是一个简单.快速的JavaBean拷贝框架,Orika使用字节代码生成来创建具有最小开销的快速映射器. 关于: 作为开发人员,我们必须为业务问题提供解决方案,我们希望利用我们的时间来做真正重 ...
- JavaBean映射工具dozer学习
阅读更多 转载自http://lishaorui.iteye.com/blog/1151513 1.简介 dozer是一种JavaBean的映射工具,类似于apache的BeanUtils.但 ...
- 常见Bean映射工具分析评测及Orika介绍
原地址:http://tech.dianwoda.com/2017/11/04/gao-xing-neng-te-xing-feng-fu-de-beanying-she-gong-ju-orika/ ...
- Bean映射工具之Apache BeanUtils VS Spring BeanUtils
背景 在我们实际项目开发过程中,我们经常需要将不同的两个对象实例进行属性复制,从而基于源对象的属性信息进行后续操作,而不改变源对象的属性信息,比如DTO数据传输对象和数据对象DO,我们需要将DO对象进 ...
- Java bean常见映射工具分析和比较
1. 概述 日常Java开发项目中,我们经常需要将对象转换成其他形式的对象,因此我们需要编写映射代码将对象中的属性值从一种类型转换成另一种类型. 进行这种转换除了手动编写大量的get/set代码,还可 ...
- EF架构~AutoMapper对象映射工具简化了实体赋值的过程
回到目录 AutoMapper是一个.NET的对象映射工具,一般地,我们进行面向服务的开发时,都会涉及到DTO的概念,即数据传输对象,而为了减少系统的负载,一般我们不会把整个表的字段作为传输的数据,而 ...
- Java微信公众号开发-外网映射工具配置
一.开发环境准备 1.一个微信公众号 2.外网映射工具(开发调试)如花生壳.ngrok工具 注:与微信对接的URL要具备以下条件a:在公网上能够访问 b:端口只支持80端口 这里使用ngrok.cc: ...
- [转]p2p端口映射工具 dog-tunnel
[转]p2p端口映射工具 dog-tunnel http://www.oschina.net/p/dog-tunnel 狗洞是一个高速的 P2P 端口映射工具,同时支持Socks5代理. 0.5版后开 ...
- 根据表结构自动生成JavaBean,史上最强最专业的表结构转JavaBean的工具(第2版)
目录: 第1版:http://blog.csdn.net/vipbooks/article/details/51912143 ...
随机推荐
- DevUI开源经验分享:从0到1开始运营你的开源项目
摘要:DevUI是面向企业中后台产品的开源前端解决方案,于2019年6月正式在GitHub开源,从当时的无人问津到去年8月累计1000 Star,再到现如今上千名社区成员.上百位贡献者.达成了3000 ...
- APP加固原理与作用
APP加固原理与作用 引言 在移动应用开发中,APP加固是一种保护应用代码逻辑的重要措施.通过对应用文件进行隐藏.混淆和加密等操作,可以有效提高软件的逆向成本,降低被破解的几率.本文将介绍APP加固的 ...
- 火山引擎 DataTester:抖音的设计团队是如何用 A/B 测试实现高效优化的?
更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 对 C 端产品而言,产品的每一个细节设置都或多或少影响着用户的产品体验,本文介绍字节跳动的 A/B 实验文化的同时 ...
- Solon Web 开发:一、开始
1.第一个Web应用 回顾一下<快速入门>里做过的事情,然后开始我们的第一个web应用 1.1.pom.xml配置 设置solon的parent.这不是必须的,但包含了大量默认的配置,可简 ...
- MongoDB 占用CPU资源过高
情况如下 db.currentOp() 发现有全表扫描 将 Collscan 对应的 Collection 建索引 db.Table1.createIndex({"DataTime" ...
- 【flask】flask-sqlalchemy使用 flask-migrate使用 flask项目演示
目录 昨日回顾 今日内容 1 flask-sqlalchemy使用 2 flask-migrate使用 3 flask项目演示 昨日回顾 类装饰器可能有两种含义: 使用类作为装饰器 装饰类的装饰器 基 ...
- # 0x54 动态规划-树形DP
A.没有上司的舞会 基础树形DP emmm,蒟蒻发现自己的DP太辣鸡了...所以来练练DP,这题的话实际上应该算是树DP的入门题吧,转移还是挺好想的. 每次在每个节点都会有个选择,就是选还是不选,如果 ...
- 如虎添翼!高德地图+Serverless 护航你的假日出行
作者 | 刘金龙(福辰) 高德团队 引言 "前方事故多发地段,请注意保持车距..." "您已疲劳驾驶,请注意休息..." "前方经过泰山旅游景 ...
- P1854-DP【绿】
首先通过这道题我收获了一个知识,那就是deque可以直接赋值,作用和vector类似就是复制一个一摸一样的deque,很好用,越来越发现deque眉清目秀了起来.以后deque可能是我最常用的STL结 ...
- qq快速打开邮箱的设置
登陆qq想快速进入邮箱,发现没有入口