【问题标题】:how to merge properties from one Java object to another in Java using Spring [SpEL]?如何使用 Spring [SpEL] 在 Java 中将属性从一个 Java 对象合并到另一个对象?
【发布时间】:2018-02-20 19:40:12
【问题描述】:

我正在使用 Spring,但对它的所有功能并不熟悉。寻找一种将字段从一个 Java 对象实例复制到另一个的好方法。我见过How to copy properties from one Java bean to another?,但我正在寻找更具体的,所以这里是详细信息:

假设我有一些 P 类的两个实例,源和目标,它们有 getter 和 setter a、b、c、d 和其他 20 个。 我想将源的属性复制到目标中,但仅适用于属性名称列表中的所有属性。源或目标中任何属性的值无关紧要。
换句话说,如果列表是 {"a", "b"}
那么我只希望发生以下情况:

P source;
P target;
List<string> properties; 

//source, target are populated. properties is {"a", "b"}  
//Now I need some Spring (SpEL?) trick to do the equivalent of:
target.setA(source.getA());
target.setB(source.getB());

【问题讨论】:

标签: java spring spring-el


【解决方案1】:

使用 Java 反射:

Field[] fields = source.getClass().getDeclaredFields();

for (Field f: fields) {
    if (properties.contains(f.getName())) {

        f.setAccessible(true);

        f.set(destination, f.get(source));
    }
}

这里有一些关于反射的教程:

http://www.oracle.com/technetwork/articles/java/javareflection-1536171.html

http://tutorials.jenkov.com/java-reflection/index.html

不过要小心,Reflection has specific use cases


使用 Spring BeanWrapper:

BeanWrapper srcWrap = PropertyAccessorFactory.forBeanPropertyAccess(source);
BeanWrapper destWrap = PropertyAccessorFactory.forBeanPropertyAccess(destination);

properties.forEach(p -> destWrap.setPropertyValue(p, srcWrap.getPropertyValue(p)));

Spring BeanWrapper 示例的致谢:https://stackoverflow.com/a/5079864/6510058

【讨论】:

  • 感谢 Leonz 提供了非常全面的答案。由于我使用的是 Spring,因此我使用了您的 BeanWrapper 解决方案。由于目前我仅限于 Java 7,因此我不得不对最后一行进行微不足道的更改。懒得发了。也许你应该...
【解决方案2】:

我认为SpEL这里不需要,可以用BeanUtils.copyProperties(Object, Object, String...)解决。根据您的示例,如果您的类具有属性 'a','b','c' 并且您只想复制前两个,则可以这样称呼它

BeanUtils.copyProperties(source, target, "c");

希望对你有帮助!

【讨论】:

  • 那么,在 Spring 中有没有一种简单的方法来获取一个类的所有属性的列表?因为我需要该列表,并且我需要从列表中删除所有属性,然后才能调用 copyProperties
  • @inor,当然,你只需要一点黑暗的反射魔法List&lt;String&gt; fieldNames = Arrays.asList(P.class.getDeclaredFields()).stream().map(Field::getName).collect(Collectors.toList());
  • 嗨,谢尔盖。感谢您的出色回答。我从中学到了我需要赶上黑魔法。我勾选了你的答案,但我会给@leonz 打勾,因为他的答案似乎更有效,因为它不需要遍历所有字段
  • @inor,没关系!很高兴社区帮助您解决了这个问题。
猜你喜欢
  • 1970-01-01
  • 2014-02-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-26
相关资源
最近更新 更多