递归地将属性从一个 bean 复制到另一个(不相同 class)(包括嵌套 bean)

Copy properties from one bean to another (not the same class) recursively (including nested beans)

哪种方法需要最少的自己编写的代码来实现一个 bean 到另一个 bean 的深度复制?目标是在源属性和目标属性按名称匹配时以自动方式执行此操作。

源主 bean:

public class SourceBean {
    private String beanField;
    private SourceNestedBean nestedBean;

    // getters and setters
}

源嵌套 bean:

public class SourceNestedBean {
    private String nestedBeanField;

    // getters and setters
}

目标主 bean:

public class TargetBean {
    private String beanField;
    private TargetNestedBean nestedBean;

    // getters and setters        
}

目标嵌套 bean:

public class TargetNestedBean {
    private String nestedBeanField;

    // getters and setters
}


使用例如Spring BeanUtils.copyProperites() 我可以用一行代码创建 SourceBeanTargetBean 的浅表副本,但它不会复制嵌套的 bean。是否有任何成熟的实用程序(不一定 Spring 框架)允许在 编写尽可能少的自己的代码时进行深度复制 (与 [=35= 几乎相同) ]())?

而如果你想在 Java 中使用深度复制,你应该使用 ObjectOutputStream 和 ObjectInputStream,你需要复制的所有 class 应该实现 Serializable。

public Object deepCopy() throws IOException, ClassNotFoundException{
    //store object in memory using serial
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream(bos);
    oos.writeObject(this);
    ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
    ObjectInputStream ois = new ObjectInputStream(bis);
    return ois.readObject();
}

使用 apache commons-lang 中的 SerializationUtils。并使您的对象可序列化。

您可以使用Dozer Mapper 进行深拷贝。参见 http://dozer.sourceforge.net/documentation/deepmapping.html

一种方法是 Jackson ObjectMapper, via the convertValue() method:

ObjectMapper mapper = new ObjectMapper();
SourceBean source = ...;
TargetBean target = mapper.convertValue(source, TargetBean.class);

请注意,convertValue() 已重载以也适用于泛型类型。还要注意 convertValue() 在某些情况下会 return 您提供的值,例如如果 SourceBean 可分配给 TargetBean。

由于 Jackson 是一个 JSON serialization/deserialization 库,convertValue() 所做的是在内存中将 source 序列化为 JSON,然后反序列化此 JSON 到 TargetBean 的一个实例中。所以高性能是不可期待的。但是,转换是用一行代码执行的。

如果需要性能,最好是手动映射。没有比这更好的了。

如果您需要简单性,请如上所述使用 Jackson。

一个很好的权衡是 Orika,一个高性能的映射器,几乎没有配置,不使用反射。