Проблема с генератором Java Builder - PullRequest
8 голосов
/ 23 ноября 2010

В моем проекте у меня есть два пакета, полные DTO, POJO только с геттерами и сеттерами.Несмотря на то, что важно, чтобы они были простыми Java-бинами (например, потому что Apache CXF использует их для создания XSD-файлов Web-служб и т. Д.), Они также ужасны и подвержены ошибкам.и объекты builder, поэтому я использую maven / gmaven для автоматического создания сборщиков для DTO.Таким образом, для приведенного выше кода автоматически генерируется FooBuilder, который я могу использовать следующим образом:

Foo foo = new FooBuilder()
           .bar("baz")
           .phleem(123)
           .build();

Я также автоматически генерирую модульные тесты для сгенерированных Строителей.Модульный тест сгенерирует оба приведенных выше кода (версия для сборщика и не для сборщика) и подтвердит, что обе версии эквивалентны с точки зрения equals() и hashcode().Способ, которым я могу достичь этого, - это иметь глобально доступную Карту со значениями по умолчанию для каждого типа свойства.Примерно так:

public final class Defaults{
    private Defaults(){}
    private static final Map<Class<?>, Object> DEFAULT_VALUES =
        new HashMap<Class<?>, Object>();
    static{
        DEFAULT_VALUES.put(String.class, "baz");
        // argh, autoboxing is necessary :-)
        DEFAULT_VALUES.put(int.class, 123);
        // etc. etc.
    }
    public static getPropertyValue(Class<?> type){
        return DEFAULT_VALUES.get(type);
    }
}

Еще один нетривиальный аспект заключается в том, что у pojos иногда есть члены коллекции.Например:

foo.setBings(List<Bing> bings)

, но в моем сборщике я хотел бы, чтобы это генерировало два метода из этого случая: метод set и метод add:

fooBuilder.bings(List<Bing> bings); // set method
fooBuilder.addBing(Bing bing); // add method

Я решил это, добавивпользовательская аннотация к полям свойств в Foo

@ComponentType(Bing.class)
private List<Bing> bings;

Builder Builder (sic) считывает аннотацию и использует значение в качестве универсального типа генерируемых методов.

Мысейчас все ближе к вопросу (извините, краткость не является одним из моих достоинств: -)).

Я понял, что этот подход к построителю может быть использован в более чем одном проекте, поэтому я думаю об измененииэто в плагин Maven.Я совершенно ясно о том, как сгенерировать плагин maven, так что это не является частью вопроса (равно как и о том, как сгенерировать допустимый исходный код Java).Моя проблема: как я могу справиться с двумя вышеупомянутыми проблемами без введения каких-либо общих зависимостей (между проектом и плагином):

<Question>

  1. Мне нужен класс Defaults (или аналогичный механизм) для получения значений по умолчанию для сгенерированных модульных тестов (это ключевая часть концепции, я бы не стал доверять автоматически сгенерированным компоновщикам, если бы они не были полностью протестированы).Пожалуйста, помогите мне найти хороший и общий способ решения этой проблемы, учитывая, что каждый проект будет иметь свои собственные доменные объекты.

  2. Мне нужен общий способ передачи универсальных типов встроительный генератор.Текущая версия на основе аннотаций, которую я использую, не является удовлетворительной, поскольку и проект, и плагин должны знать одну и ту же аннотацию.

</Question>

Есть идеи?

Кстати: я знаю, что реальный ключевой момент использования строителей - сделать объекты неизменяемыми.Я не могу сделать мой неизменяемым, потому что стандартные Java-бины необходимы, но я использую AspectJ для обеспечения того, чтобы ни set-методы, ни конструкторы не вызывались нигде в моей базе кода, кроме как в сборщиках, поэтому для практических целей результирующие объекты являются неизменяемыми.

Также: Да, мне известны существующие плагины для IDE Builder-генератора.Это не соответствует моей цели, я хочу автоматизированное решение, которое всегда обновляется всякий раз, когда изменяется базовый код.


Мэтт Б запросил некоторую информацию о том, как я генерирую мои сборщики.Вот что я делаю:

Я читаю класс для каждого отражения, использую Introspector.getBeanInfo(clazz).getPropertyDescriptors(), чтобы получить массив дескрипторов свойств.У всех моих строителей базовый класс AbstractBuilder<T>, где T будет Foo в приведенном выше случае.Вот код класса Abstract Builder .Для каждого свойства в массиве PropertyDescriptor создается метод с именем свойства.Это будет реализация FooBuilder.bar(String):

public FooBuilder bar(String bar){
    setProperty("bar", bar);
    return this;
}

метод build() в AbstractBuilder создает экземпляр объекта и назначает все свойства в его карте свойств.

Ответы [ 2 ]

2 голосов
/ 23 ноября 2010

POJO - это объект, который не следует за спуком Java Bean.то есть.он не имеет сеттеров / геттеров.

JavaBeans не обязаны иметь сеттеры, если вы не хотите, чтобы они вызывались, не генерируйте их.(Ваш конструктор может вызвать пакет локальным или частным конструктором для создания ваших неизменяемых объектов)

1 голос
/ 18 декабря 2011

Вы смотрели на Дизель ?Это генератор Builder.

  1. Он обрабатывает универсальные типы, поэтому он может быть полезен здесь для вопроса 2
  2. Он генерирует все интерфейсы и план реализации на основе описания XMLфайл.Вы можете с помощью самоанализа сгенерировать этот XML (или даже перейти непосредственно к более низкому API)
  3. Он входит в состав подключаемого модуля maven.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...