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

Java 递归地将属性从一个bean复制到另一个bean(不是同一个类)(包括嵌套bean),java,spring,javabeans,spring-bean,Java,Spring,Javabeans,Spring Bean,哪种方法需要最少的自己编写的代码来实现一个bean到另一个bean的深度复制?目标是在源属性和目标属性按名称匹配时自动执行此操作 源主bean: public class SourceBean { private String beanField; private SourceNestedBean nestedBean; // getters and setters } public class TargetBean { private String bean

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

源主bean:

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

    // getters and setters
}
public class TargetBean {
    private String beanField;
    private TargetNestedBean nestedBean;

    // getters and setters        
}
源嵌套bean:

public class SourceNestedBean {
    private String nestedBeanField;

    // getters and setters
}
public class TargetNestedBean {
    private String nestedBeanField;

    // getters and setters
}
目标主bean:

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

    // getters and setters
}
public class TargetBean {
    private String beanField;
    private TargetNestedBean nestedBean;

    // getters and setters        
}
目标嵌套bean:

public class SourceNestedBean {
    private String nestedBeanField;

    // getters and setters
}
public class TargetNestedBean {
    private String nestedBeanField;

    // getters and setters
}


例如,使用一行代码,我可以创建一个
SourceBean
TargetBean
的浅拷贝,但它不会复制嵌套bean。是否有成熟的实用程序(不一定是Spring Framework)允许在编写尽可能少的代码时进行深度复制(与BeanUtils.copyProperties()非常相似)

而如果要在Java中使用深度复制,则应该使用ObjectOutputStream和ObjectInputStream,并且需要复制的所有类都应该实现可序列化

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进行深度复制。请参见

一种方法是通过:

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();
}
请注意,
convertValue()
被重载以同时处理泛型类型。还要注意,
convertValue()
在某些情况下会返回您提供的值,例如如果SourceBean可分配给TargetBean

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

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

如果您需要简单,请使用上面解释的Jackson


一个很好的折衷办法是,一个几乎没有配置的高性能映射器不使用反射。

使用序列化进行深度映射copy@TheLostMind我认为只有当它们是同一个类时,这才有效。@M.Deinum不完全有效。您提到的问题是一个更通用的问题(bean映射),而我需要的是用最少的设置代码以非常简单的方式按文件名克隆
possible@TheLostMind从类
SourceBean
的对象复制到类
TargetBean
的对象,它们没有共同的祖先。@Realdisponse您是对的,序列化不是一个选项,因为我们讨论的是两个不同的类。可以使用Dozer w/o xml配置,也可以通过名称定义映射策略,因为我不想手动定义任何特定映射。您可以改为使用API映射:。我认为编写通用帮助器方法来复制您的对象并不困难。是的,这一个方法不使用XML,但我仍然必须定义要复制的字段,因此假设我有几十个bean,很遗憾这不是一个选项。无论如何,感谢您的帮助,upvotedsource ant target对象属于不同的类Source ant target对象属于不同的类我认为这可以作为一个答案,尽管我仍然不确定是否会在生产中使用它,因为可能存在性能问题。@SergeyPauk我唯一能做出回应的是,你应该运行一些基准测试,看看时间是否合适这是一个错误的答案,convert选项不会创建一个不可变的bean。如果bean中包含非原语类型,那么更改目标bean将更改源bean。在我的情况下,它会改变两种情况下的值,但不起作用。你的应用程序工作正常,但我的没有。。用同样的杰克逊版本。。。在代码检查之后,我发现了原因。在我的例子中,我复制的是相同的bean类型:SourceBean target=mapper.convertValue(source,SourceBean.class);但在您的例子中,您正在克隆到另一个bean类型。克隆到同一类型(deepbean副本)不是不变的。因此,您的答案适用于问题案例,但不适用于其他案例(我的案例)