Подтвердить что ты не робот

Комплекс 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, поскольку он не влияет на потребителей старой службы.

Спасибо.

4b9b3361

Ответ 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, но с наследованием).