9

我有一堆第三方 Java 类,它们对本质上相同的属性使用不同的属性名称:

public class Foo {
   public String getReferenceID();
   public void setReferenceID(String id);
   public String getFilename();
   public void setFilename(String fileName);
}

public class Bar {
   public String getRefID();
   public void setRefID(String id);
   public String getFileName();
   public void setFileName(String fileName);
}

我希望能够以规范化的形式解决这些问题,这样我就可以多态地对待它们,这样我就可以用 Apache BeanUtils 做一些事情,比如:

PropertyUtils.copyProperties(object1,object2);

显然,为每个类编写一个适配器是微不足道的......

public class CanonicalizedBar implements CanonicalizedBazBean {
    public String getReferenceID() {
        return this.delegate.getRefID();
    }
    // etc.
}

但我想知道那里有更普遍和动态的东西吗?需要属性名称等价的一对多映射和委托类并生成适配器的东西?

4

5 回答 5

6

我从未使用过它,但我认为您正在寻找Dozer

Dozer 是一个 Java Bean 到 Java Bean 的映射器,它递归地将数据从一个对象复制到另一个对象。通常,这些 Java Bean 将具有不同的复杂类型。

Dozer 支持简单属性映射、复杂类型映射、双向映射、隐式-显式映射以及递归映射。这包括映射集合属性,这些属性也需要在元素级别进行映射。

Dozer 不仅支持属性名称之间的映射,还支持类型之间的自动转换。大多数转换方案都支持开箱即用,但 Dozer 还允许您通过 XML 指定自定义转换。

于 2012-06-21T10:01:36.467 回答
4
  1. 第一个选项是推土机

  2. 第二个选项是带有调整的Smooks框架。使用 Smook 的图形映射器将是有益的。

  3. 另一种选择是带有自定义映射器的XStream 。

于 2012-06-23T19:29:19.237 回答
2

也许是这样的:

public class CanonicalizedBar implements CanonicalizedBazBean {
public String getReferenceID() {
    Method m = this.delegate.getClass().getDeclaredMethod("getReferenceID");
    if(m == null)
        m = this.delegate.getClass().getDeclaredMethod("getRefID");
    ...
    return m.invoke();
}
// etc.
}
于 2012-06-27T00:31:31.730 回答
2

虽然,我个人从未使用过它。我注意到一个名为orika的项目被认为具有最佳性能和自动理解许多此类映射的能力。无论如何,它还支持自定义映射并使用生成的代码来隐式定义适配器。

您还可以定义自定义映射器,也就是说,如果您知道如何规范成员名称,则可以使用该知识来构建适用于所有对象的映射。例如:

DefaultFieldMapper myDefaultMapper = new DefaultFieldMapper() {
   public String suggestMapping(String propertyName, Type<?> fromPropertyType) {
      // split word according to camel case (apache commons lang)
      String[] words= StringUtils.splitByCharacterTypeCamelCase(propertyName);
      if(words[0].length() > 6) {
         // trim first camel-cased word of propery name to 3 letters
         words[0]= words[0].substring(0,2);
         return StringUtils.join(words);
      } else {
         // remains unchanged
         return propertyName;
      }   
   }
}

mapperFactory.registerDefaultFieldMapper(myDefaultMapper );
于 2012-06-27T03:04:03.477 回答
1

我没有做太多,但你可以使用面向方面的编程来做到这一点。

我认为您应该能够为每个内部调用真实方法的类添加一个方法。看到这篇文章的一半,它谈到了 mixins。

AspectJ可能是最流行的实现。

于 2012-06-27T05:36:38.457 回答