Fastest Java Bean Mapper? BeanUtils, Dozer, Orika, BeanCopier Compared
This article compares the usage, performance, and internal implementation of popular Java bean‑mapping tools—Spring BeanUtils, Apache BeanUtils, CGLIB BeanCopier, Dozer, and Orika—providing benchmark results, code examples, and detailed analysis to help developers choose the most efficient solution for their layered architectures.
Background
In layered code architectures, objects often need to be converted or copied between layers, which can become repetitive and cumbersome. Tools such as BeanUtils, BeanCopier, Dozer, and Orika have emerged to perform these operations efficiently. This article introduces these tools, presents performance comparisons, and analyses their underlying principles.
Performance Analysis
The benchmarks were run with JMH. Simple objects containing basic types were copied 1,000, 10,000, and 100,000 times, with a warm‑up iteration to account for caching and pre‑compilation. The results (average time in microseconds) show the ranking:
Score represents average execution time (µs). BeanCopier > Orika > Spring BeanUtils > Dozer > Apache BeanUtils. The differences stem from each tool’s implementation strategy.
Spring BeanUtils
Usage
Most commonly used because it is bundled with Spring. Simple call:
BeanUtils.copyProperties(sourceVO, targetVO);Principle
Spring BeanUtils uses Java's Introspector to obtain PropertyDescriptor objects for both source and target classes. It matches properties with identical names and types, then reads the value via the getter and writes it via the setter. BeanInfo and PropertyDescriptor caches improve performance.
Summary
The implementation is straightforward, which explains its relatively high performance, but it only works when property names and types match exactly.
Apache BeanUtils
Usage
Usage is identical to Spring's: BeanUtils.copyProperties(targetVO, sourceVO); Note the reversed parameter order.
Principle
Apache BeanUtils also relies on Introspector and caches BeanInfo and PropertyDescriptor. It adds extra features such as Map support, DynaBean handling, and property expression parsing, which introduce overhead and reduce performance compared to Spring BeanUtils.
Summary
Functionally similar to Spring BeanUtils but slower; Alibaba's Java guidelines discourage its use.
BeanCopier (CGLIB)
Usage
Define a copier for source and target classes:
BeanCopier bc = BeanCopier.create(SourceVO.class, TargetVO.class, false);
bc.copy(sourceVO, targetVO, null);Principle
BeanCopier generates bytecode at runtime using CGLIB. It creates a class that directly invokes the source getter and target setter, avoiding reflection. This bytecode generation yields performance close to hand‑written copy code. The create method builds a Generator, which produces a class implementing the copy logic.
Summary
BeanCopier offers the highest speed among the tested tools, but it only copies properties with identical names and types. When a Converter is used, all conversion logic must be handled manually.
Dozer
Usage
Dozer supports rich mapping features, including implicit name mapping, type conversion, explicit field mapping, exclusion, deep mapping, date formatting, custom converters, and XML/annotation configuration. Example configuration:
Mapper mapper = DozerBeanMapperBuilder.create()
.withMappingBuilder(new BeanMappingBuilder() {
@Override
protected void configure() {
mapping(SourceVO.class, TargetVO.class)
.fields("fullName", "name")
.exclude("in");
}
})
.build();
TargetVO target = mapper.map(sourceVO, TargetVO.class);Principle
Dozer also uses reflection/Introspector but adds many features such as custom converters, event listeners, and support for collections, maps, and deep object graphs. The core mapping flow builds a ClassMap and then processes each field, handling primitives, collections, maps, enums, and custom objects recursively.
Summary
Dozer is feature‑rich but its reliance on reflection makes it slower than BeanCopier and Orika. Suitable when performance is not critical and flexibility is required.
Orika
Usage
Orika combines the strengths of the previous tools. It uses Javassist to generate bytecode, offering high performance and extensive features. Example setup:
MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
mapperFactory.classMap(SourceVO.class, TargetVO.class)
.field("fullName", "name")
.field("type", "enumType")
.exclude("in")
.byDefault()
.register();
MapperFacade mapper = mapperFactory.getMapperFacade();
TargetVO target = mapper.map(sourceVO, TargetVO.class);Principle
Orika builds a MapperFactory that registers class maps. When the first mapping is requested, it generates a mapper class (e.g., Orika_TargetVO_SourceVO_Mapper...) using Javassist. The generated class contains mapAtoB and mapBtoA methods with direct field assignments, collection handling, and custom converter calls. The bytecode is written to disk (optional) and loaded at runtime, delivering performance close to hand‑written code.
Summary
Orika provides a powerful, high‑performance solution with rich mapping capabilities, making it the recommended choice for most backend projects.
Overall Summary
By comparing BeanUtils, BeanCopier, Dozer, and Orika, we see a clear trade‑off between flexibility and speed. BeanCopier and Orika deliver the best performance; Dozer offers the most features but is slower; Spring BeanUtils provides a good balance for simple cases. For most backend development needs, Orika is the preferred tool.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
