Комплекс Bean Сопоставление
Я пытаюсь найти лучшее решение для проблемы, которую я имею, с сопоставлением простой структуры 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) {...}
...
}
Конечный результат будет выглядеть примерно так: где значение равно значению в исходной структуре:
public class Example2{
Presentable<String> value1;
Presentable<Boolean> value2;
Presentable<Example3> value3;
public Presentable<String> getValue1(){...}
public void setValue1(){...}
...
}
Есть ли решение этой проблемы без написания класса стиля Example2 и копирования в каждом отдельном значении? Я открыт для изменения класса Example1, поскольку он не влияет на потребителей старой службы.
Спасибо.
Ответы
Ответ 1
Вы можете использовать в основном AOP (аспектно-ориентированное программирование) с помощью Spring. В 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
Этот пример/ответ может быть полезен:
Метод перехвата с помощью spring AOP с использованием только аннотаций
Ответ 2
Поэтому я не уверен, правильно ли я тебя понял. Однако...
Это место, где мы можем очень легко использовать отражение.
Для нашего класса Example1.class мы вызываем getDeclaredMethods, getDeclaredFields (в простом случае) или getMethods, getFields в более сложных (простое pojo, но с наследованием). Возможно, вам понадобится простая логика, например, для удаления полей с помощью модификатора static
или что-то в этом роде.
Для каждого метода/поля мы получаем соответствующий метод/поле из примера2.class с getMethod (имя строки) или getField (имя строки)
И установите наше значение для нового объекта через поле или сеттер. Если есть проблема с такими модификаторами, как private, мы используем 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;
}
Очень легко сделать более общий метод из этого выше, если это необходимо.
Вам не нужна внешняя библиотека или инструмент.
Ответ 3
Вы можете использовать Jackson ObjectMapper
и сконфигурировать [Dozer][1]
mapper, чтобы выполнить это сложное отображение bean и JSON
установить связь между приложением и браузером.
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.
Шишир
Ответ 4
Чтобы включить AspectJ, вам нужно aspectjrt.jar, aspectjweaver.jar и spring -aop.jar.
Для нашего класса Example1.class мы вызываем getDeclaredMethods, getDeclaredFields (в простом случае) или getMethods, getFields более сложным (простое pojo, но с наследованием).