Как я могу расширить Java-код, сгенерированный инструментами JAXB, CXF или Hibernate?

Сгенерированный исходный код Java, например

  • код, сгенерированный с помощью инструментов Hibernate.
  • код, сгенерированный с привязкой схемы JAXB (xjc)
  • код, созданный с помощью WDSL2Java (cxf)

все сгенерированные классы являются типами "объект ценности", без бизнес-логики. И если я добавлю методы к сгенерированному исходному коду, я потеряю эти методы, если повторю генерацию исходного кода.

Предоставляют ли эти средства генерации кода Java способы "расширения" сгенерированного кода?

Например,

  • для переопределения метода ToString (для ведения журнала)
  • для реализации шаблона посетителя (для анализа/проверки данных)

Ответы

Ответ 1

Для JAXB см. Добавление действий.

В основном вы настраиваете JAXB для возврата собственного экземпляра объекта, который вы обычно ожидаете. В приведенном ниже примере вы создаете новый объект PersonEx, который расширяет объект Person JAXB. Этот механизм хорошо работает в том, что вы извлекаете из сгенерированных классов и не изменяете классы или схемы JAXB вообще.

package org.acme.foo.impl;

class PersonEx extends Person {
  @Override
  public void setName(String name) {
    if(name.length()<3) throw new IllegalArgumentException();
    super.setName(name);
  }
}

@XmlRegistry
class ObjectFactoryEx extends ObjectFactory {
  @Override
  Person createPerson() {
    return new PersonEx();
  }
}

Обратите внимание, что директива @Override важна в случае изменения объекта JAXB - это предотвратит сиротство вашей настройки.

Ответ 2

Что касается Hibernate, вы можете настроить файлы шаблонов, используемые в генерации кода, чтобы изменить их поведение. Если вы хотите настроить инструменты HIbernate, вы можете редактировать, например: dao/daohome.ftl

Вы даже можете добавлять поля к выводу "toString()", редактируя файлы .hbm.xml

...
<property name="note" type="string">
    <meta attribute="use-in-tostring">true</meta>
    <column name="note" />
</property>
...

Как для ведения журнала, так и для проверки вы можете использовать AOP с AspectJ (я не рекомендую возиться с сгенерированным кодом, так как вы можете хотите построить это с нуля много раз).

Ответ 3

Сначала я бы повторил, что изменение сгенерированного кода связано с множеством проблем, связанных с ним, и что, по возможности, этого следует избегать. Тем не менее иногда это непрактично, чтобы избежать или больше усилий, чем просто иметь дело с изменениями, когда код восстанавливается.

К сожалению, java не поддерживает концепцию частичных классов, которые имеет С#. Это именно то, чтобы решить эту проблему.

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

Лучший вариант, если вы действительно хотите это сделать, - сначала сгенерировать файлы, но сразу же проверить их в репозитории управления версиями. Затем внесите изменения, проверьте это.

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

Это не поможет вам, если генератор кода внезапно генерирует радикально другой код (скажем, новую версию), но в этих случаях добавляется какой-либо код, который не был просто дополнительным методом удобства, основанным на данных/методах, уже открытых публично) будут иметь проблемы независимо от того, как они смешиваются с классом. Система контроля версий все еще помогает, так как она также записывает исходные изменения, чтобы вы могли видеть, что вы добавили ранее, и что, можно предположить, вам нужно воссоздать в новом стиле.

Ответ 4

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

Я рекомендую вам изучить параметры команды инструментов, чтобы убедиться, что они позволяют вам немного гибкости. Некоторые инструменты могут генерировать абстрактные классы или интерфейсы вместо конкретных классов. Если это невозможно, создайте объект домена, который включает автогенерируемый объект в качестве переменной-члена.

Ответ 5

Способ, которым я использовал Hibernate, - это генерировать базовые классы, которые я затем расширяю. Я добавляю всю свою бизнес-логику (если есть) в эти подклассы. Я также часто меняю шаблоны FreeMarker, используемые Hibernate для дальнейшей настройки сгенерированных классов.

Ответ 6

Цитата АОП является хорошей. Я добавлю Spring, который имеет очень хорошие функции AOP, встроенные.

Ответ 7

Посмотрите

http://code.google.com/p/jaxb-method-inserter/

Его небольшой плагин для JAXB, который я написал, его довольно просто использовать. Надеюсь, что это поможет.