Object Copying in Java: Comparing Apache BeanUtils and Spring BeanUtils
This article explains the concepts of shallow and deep copying in Java, demonstrates how to use Apache BeanUtils and Spring BeanUtils for property copying between objects, compares their implementations and performance, and recommends alternative tools for efficient object mapping.
In Java projects we often need to copy properties from one object instance to another (for example, from a data object DO to a DTO) without altering the source object's state.
Java distinguishes between shallow copy and deep copy: a shallow copy duplicates only the primitive fields and copies references for object fields, while a deep copy creates new instances for referenced objects and copies their contents.
In short:
Shallow copy: value copy for primitives, reference copy for objects.
Deep copy: value copy for primitives, new object creation and content copy for referenced objects.
Apache BeanUtils provides a simple way to copy properties. Example usage:
public class PersonSource {
private Integer id;
private String username;
private String password;
private Integer age;
// getters/setters omitted
}
public class PersonDest {
private Integer id;
private String username;
private Integer age;
// getters/setters omitted
}
public class TestApacheBeanUtils {
public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
PersonSource personSource = new PersonSource(1, "pjmike", "12345", 21);
PersonDest personDest = new PersonDest();
BeanUtils.copyProperties(personDest, personSource);
System.out.println("persondest: " + personDest);
}
}
// Output: persondest: PersonDest{id=1, username='pjmike', age=21}The core method used by Apache BeanUtils is:
public static void copyProperties(Object dest, Object orig) throws IllegalAccessException, InvocationTargetException {
BeanUtilsBean.getInstance().copyProperties(dest, orig);
}By default, Apache BeanUtils performs a shallow copy and its implementation adds many checks (type conversion, accessibility, etc.), which leads to poor performance. Alibaba's Java coding guidelines explicitly advise against using Apache BeanUtils for property copying.
Spring BeanUtils offers a similar copyProperties method but with a much simpler implementation that directly copies matching property values via getter/setter methods. Example usage:
public class TestSpringBeanUtils {
public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
PersonSource personSource = new PersonSource(1, "pjmike", "12345", 21);
PersonDest personDest = new PersonDest();
BeanUtils.copyProperties(personSource, personDest);
System.out.println("persondest: " + personDest);
}
}The underlying implementation roughly follows:
private static void copyProperties(Object source, Object target, @Nullable Class
editable, @Nullable String... ignoreProperties) throws BeansException {
Assert.notNull(source, "Source must not be null");
Assert.notNull(target, "Target must not be null");
Class
actualEditable = target.getClass();
if (editable != null) {
if (!editable.isInstance(target)) {
throw new IllegalArgumentException("Target class [" + target.getClass().getName() + "] not assignable to Editable class [" + editable.getName() + "]");
}
actualEditable = editable;
}
PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);
for (PropertyDescriptor targetPd : targetPds) {
Method writeMethod = targetPd.getWriteMethod();
if (writeMethod != null && (ignoreProperties == null || !Arrays.asList(ignoreProperties).contains(targetPd.getName()))) {
PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName());
if (sourcePd != null) {
Method readMethod = sourcePd.getReadMethod();
if (readMethod != null && ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType())) {
Object value = readMethod.invoke(source);
writeMethod.invoke(target, value);
}
}
}
}
}This method safely copies matching properties, skipping ignored ones and ensuring type compatibility, but it still requires that the source and target have properties of the same name and compatible types.
Conclusion : Apache BeanUtils is inefficient and not recommended; Spring BeanUtils is a lightweight alternative, and other dedicated mapping frameworks such as Dozer or ModelMapper can be used for more advanced scenarios.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
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.