Orika User Guide

Orika simpler, lighter and faster Java bean mapping

作为开发人员,我们必须为业务问题提供解决方案,我们希望利用我们的时间来做真正重要的事情。在现在这个时代,企业应用程序变得越来越复杂,有大量的体系结构和设计约束。

设计的约束会产生大量的机械工作。很多的开源项目例如:Spring,Guice,Hibernate,Wicket,….等等,解放我们的双手。我们有很多可用的选项来解决整个问题的每个部分。但是对于这些不同的tools/frameworks/libraries。它通常需要我们把对象转换格式化用来适应不同的APIs,或者因为我们设计的原因也需要在不同的业务层转换格式化对象。为了完成这事件,我们只需要编写映射代码来将值从一种类型复制到另一种类型这种相当无聊的任务。

1、Orika

在一个中型到大型的项目中,这样的映射代码可以达到相当大的工作量(枯燥的)工作,而这些工作很难维护、测试和调试。

Orika企图在牺牲一点性能的情况下为你这种完全极度枯燥乏味的的工作。

它将自动收集类的元数据来生成映射对象,这些映射对象可以一起使用,以递归地将数据从一个对象图复制到另一个对象图中。Orika试图提供许多方便的功能,同时保持相对简单和开放的状态——让你有可能扩展和调整它,以满足你的需要。

2、Getting Started

2.1 Installation

为了在你的项目中使用Orika,你只需要在maven中像以下添加依赖。

<dependency>
   <groupId>ma.glasnost.orikagroupId>
   <artifactId>orika-coreartifactId>
   <version>1.4.2version>
dependency>

如果你并没有使用maven,你也可以查看[Downloads]手动下载最新版本。
注意:Orika它自身很存在依赖以下的版本:

  • javassist (v 3.12.0+)
  • slf4j (v 1.5.6+)
  • paranamer (v 2.0+)

3、Usage

Orika映射框架的最基本的就是MapperFactory这个class.通过这个class你可以配置一些映射,获取到MapperFacade来执行真正的映射工作和。一个非常基础的例子如下:

3.1 Construct a MapperFactory

MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();

3.2 Register field mappings, converters, custom mappers, concrete types, etc.

一旦你构造了MapperFactory实例,你就能够使用它为你希望映射的对象来注册field映射,自定义映射。最后获取MapperFacade实例用来执行真正的映射。如果你希望映射的对象具有匹配的名称,你就不需要再为它们注册映射了。

假设你映射的对象的一些字段的名称并不匹配,你可以通过ClassMapBuider API来为这些不同的fields注册映射关系。这个API可以通过像以下的方式使用classMap(typeA, typeB)方法来做到:

mapperFactory.classMap(PersonSource.class, PersonDestination.class)
   .field("firstName", "givenName")
   .field("lastName", "sirName")
   .byDefault()
   .register();

在上面我们通过调用mapperFactory的classMap()方法来创建了一个ClassMapBuilder实例,然后我们使用field(fieldA, fieldB)方法来指定在对象PersonSource上firstName属性应该映射到PersonDestination中的givenName属性上去。同样的把lastName属性映射到sirName属性上去;然后我们使用byDefault()方法来指定剩下的通过byDefault方式来映射。也就是以2个对象的field的名称来匹配。最后我们使用refister()方法来注册这个映射到MapperFactory中。

3.3 Map objects using the MapperFacade

映射的一般模式涉及到使用MapperFacade中的map(objectA, B.class)方法。它将会实例化一个B.class的新对象并且把映射objectA中的property值到它里面。下面是一个基本的例子:

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);

映射也可以使用MapperFacade中的map(objectA, objectB)方法在就地执行.

3.4 Map objects using the BoundMapperFacade

在需要映射的特定类型的情况下,可以使用绑定的mapper外观,这通常比使用标准的mapper facade提供更好的性能。下面显示了BoundMapperFacade的一个示例:

BoundMapperFacade boundMapper = 
   mapperFactory.getMapperFacade(PersonSource.class, PersonDest.class);

PersonSource source = new PersonSource();
// set some field values
...
// map the fields of 'source' onto a new instance of PersonDest
PersonDest destination = boundMapper.map(source);

也可以通过在BoundMapperFacade上使用map(objectA,objectB)方法来执行映射。

要使用绑定映射器映射反向方向,可以使用mapReverse(objectB)方法。

对于就地映射和反向映射,使用mapReverse(objectB,objectA)方法。

4、performance

还有其代码库也能解决这种问题:

  • 他们中的一些只能满足部分自动映射.例如,Spring框架的BeanUtils功能只局限于只有一个类的原始类型和字段。它不能将对象层次结构转换为另一个对象层次结构。

  • 另一些提供了映射过程的完全自动化(例如Dozer),他们允许处理复杂的情况,比如将对象的映射表映射到原语的映射。自动化通常以性能下降为代价。更复杂的模型转换为映射对象的时间越长。这通常是由于映射库经常使用反射和动态类型解析来支持转换的通用逻辑。

让我们来比较上面列举的所有备选方案:

用于测试的数据模型包括通常出现在Java bean中的组合,例如:

  • primitives
  • object types
  • collections
  • enums

测试环境:

  • OS: Linux 2.6.32 x86_64
  • CPU: 2.0GHz 4MB cache × 8 cores
  • RAM: 16GB
  • JVM 1.7
-Xmx1g 
-Xms1g 
-XX:MaxPermSize=128m 
-XX:NewSize=512m 
-XX:MaxNewSize=512m 
-XX:SurvivorRatio=6 
-XX:+UseCompressedOops 
-XX:+UseConcMarkSweepGC 
-XX:+UseParNewGC 
-XX:+CMSIncrementalMode
  • Number of iterations 1 000 000

当测试的时候并没有发生Major GC.以下是测试结果:

Indicator Dozer Orika Manual(手动)
Min, nano seconds 290 000 21 000 3 000
Mid, nano seconds 318 000 32 000 4 000
90%, nano seconds 390 000 41 000 5 000
95%, nano seconds 436 000 45 000 5 000
99%, nano seconds 534 000 54 000 6 000
99.9%, nano seconds 730 000 114 000 33 000
99.99%, nano seconds 1 607 000 374 000 65 000
99.999%, nano seconds 7 574 000 1 032 000 580 000
99.9999%, nano seconds 21 171 000 7 952 000 1 387 000
Max, nano seconds 21 171 000 222 581 000 9 810 000

Orika有最大的延迟,这与一般的分布不同。这种延迟在第一次转换时只出现一次,当Orika实际为mappers执行代码生成时。

Orika的延迟有相当大的偏差,这是由Orika所做的不必要的对象所造成的。例如,当字符串从变量转移到另一个变量时,将使用与空字符串连接的连接创建新的字符串。

在一般的测试中,Orika几乎和手工编写的代码一样高效,而且比Dozer的性能要高得多。

参考资料:
Orika 官网
Dozer vs Orika vs Manual

你可能感兴趣的:(Java,Architecture)