复杂Bean映射

时间:2014-02-05 17:19:13

标签: java java-ee javabeans java-6

我正在尝试找到解决我发送到基于浏览器的JavaScript应用程序的简单bean结构的问题的最佳解决方案。当前的要求是管理旧Java后端的大部分显示控制。目前,我们有一个服务样式层,它生成的值对象没有内置显示逻辑,如:

public class Example1 {
    String value1;
    Boolean value2;
    Example3 value3;

    public String getValue1(){...}
    public void setValue1(){...}
    ....
 }

我的目标是能够在所有字段上映射通用结构,以便添加前端所需的新显示结构。我想只管理原始结构类(Example1类)结构,只需在包装器中将额外值设置为旧服务层。

通用结构将采用以下类的形式:

public class Presentable<T> {
    T value;
    boolean visible = true; 
    boolean mandatory = false;
    List<String> errors = new ArrayList<>();

    public T getValue() {...}
    public void setValue(T value) {...}
    ...
}

最终结果类似于以下内容,其中value等于原始结构中的值:

public class Example2{
    Presentable<String> value1;
    Presentable<Boolean> value2;
    Presentable<Example3> value3;

    public Presentable<String> getValue1(){...}
    public void setValue1(){...}
    ...
}

如果没有编写Example2样式类并复制每个值,是否有解决此问题的方法?我愿意修改Example1类,因为它不会影响旧服务的使用者。

感谢。

4 个答案:

答案 0 :(得分:4)

你可以在Spring中使用基本的AOP(面向方面​​编程)。在Spring,您可以使用所需的额外信息创建代理对象。 好的起点是: http://www.mkyong.com/spring3/spring-aop-aspectj-annotation-example/

面向方面编程的官方页面: http://docs.spring.io/spring/docs/3.0.x/spring-framework-reference/html/aop.html

此示例/答案可能很有用: Intercepting method with Spring AOP using only annotations

答案 1 :(得分:1)

所以我不确定我是否正确地理解了你。然而...

这是一个我们可以很容易地使用反射的地方。

对于我们的类Example1.class,我们调用getDeclaredMethods,getDeclaredFields(在简单用例中)或getMethods,getFields更复杂(简单的pojo但具有继承)。您可能需要一些简单的逻辑来删除带有static修饰符的字段或类似的字段。

对于每个方法/字段,我们从Example2.class获取带有getMethod(String name)或getField(String name)的适当方法/字段

通过field或setter将我们的值设置为新对象。如果私有修饰符出现问题,我们使用setAccessible。

一些简单用例的代码:

public Example2 decorateWithWrapper(Example1 obj) {
    Example2 wrapped = new Example2();
    for (Field field : obj.getClass().getDeclaredFields()) {
        Field toAssign = wrapped.getClass().getField(field.getName());
        toAssign.setAccessible(true);
        toAssign.set(wrapped, field.get(obj));
    }
    return wrapped;
}

如果需要,可以很容易地从上面做出更通用的方法。

您不需要任何外部库或工具。

答案 2 :(得分:1)

您可以使用Jackson ObjectMapper并配置[Dozer][1]映射器来执行此复杂的bean映射,并让JSON在应用程序和&amp;之间进行通信。浏览器。

Dozer可让您将一个类映射到其他字段。 Dozer映射的基本代码如下所示:

<mappings>          
  <mapping>
    <class-a>org.dozer.vo.TestObject</class-a>
    <class-b>org.dozer.vo.TestObjectPrime</class-b>
    <!-- Any custom field mapping xml would go here -->
  </mapping>
</mappings>

此处,在上面的示例中,TestObject的所有变量都映射到TestObjectPrime。对于您的情况,您需要为此配置添加自定义映射,如下所示:

<mapping>
  <class-a>org.dozer.vo.deep.SrcDeepObj</class-a>
  <class-b>org.dozer.vo.deep.DestDeepObj</class-b>

  <field>
    <a>srcNestedObj.src1</a>
    <b>dest1</b>
  </field>

  <field>
    <a>srcNestedObj.src2</a>
    <b>dest2</b>
  </field>

  <field>
    <a>srcNestedObj.srcNestedObj2.src5</a>
    <b>dest5</b>
  </field>

  <field><!-- java.util.List to java.util.List -->
    <a>srcNestedObj.hintList</a>
    <b>hintList</b>
    <a-hint>java.lang.String</a-hint>         
    <b-hint>java.lang.Integer</b-hint> 
  </field>

  <field>
    <a>srcNestedObj.hintList2</a>
    <b>hintList2</b>
    <a-hint>org.dozer.vo.TheFirstSubClass</a-hint>
    <b-hint>org.dozer.vo.TheFirstSubClassPrime</b-hint> 
  </field>

  <field copy-by-reference="true">
    <a>srcNestedObj.hintList3</a>
    <b>hintList3</b>
  </field-deep>

</mapping>

正如推土机教程所说:

  

可以映射深层属性。一个例子就是你   有一个具有String属性的对象。你的另一个对象有一个字符串   属性,但它在对象图中有几个层次。在里面   DestDeepObj下面的示例在对象中具有嵌套属性   需要映射的图形。深度字段支持类型提示   映射。属性copy-by-reference,type = one-way,和   也可以使用关系型。

以上示例摘自Dozer documentation

Shishir

答案 3 :(得分:0)

要启用AspectJ,您需要 aspectjrt.jar,aspectjweaver.jar spring-aop.jar 。 对于我们的类Example1.class,我们调用getDeclaredMethods,getDeclaredFields(在简单用例中)或getMethods,getFields更复杂(简单的pojo但具有继承)。

相关问题