我正在尝试找到解决我发送到基于浏览器的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类,因为它不会影响旧服务的使用者。
感谢。
答案 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但具有继承)。