Какой смысл классов JAXB 2 ObjectFactory?
Я новичок в использовании JAXB, и я использовал JAXB 2.1.3 xjc для создания набора классов из моей XML-схемы. В дополнение к генерации класса для каждого элемента в моей схеме он создал класс ObjectFactory.
Кажется, что ничего не мешает мне напрямую создавать элементы, например.
MyElement element = new MyElement();
тогда как учебники, похоже, предпочитают
MyElement element = new ObjectFactory().createMyElement();
Если я смотрю в ObjectFactory.java, я вижу:
public MyElement createMyElement() {
return new MyElement();
}
так что сделка? Почему я должен даже поддерживать класс ObjectFactory? Я предполагаю, что он также будет перезаписан, если я буду перекомпилировать из измененной схемы.
Ответы
Ответ 1
Обратная совместимость - не единственная причина.:-P
С более сложными схемами, такими как те, которые имеют сложные ограничения на значения, которые может иметь содержимое элемента, иногда вам нужно создавать фактические объекты JAXBElement
. Они обычно не являются тривиальными для создания вручную, поэтому методы create*
делают тяжелую работу для вас. Пример (из схемы XHTML 1.1):
@XmlElementDecl(namespace = "http://www.w3.org/1999/xhtml", name = "style", scope = XhtmlHeadType.class)
public JAXBElement<XhtmlStyleType> createXhtmlHeadTypeStyle(XhtmlStyleType value) {
return new JAXBElement<XhtmlStyleType>(_XhtmlHeadTypeStyle_QNAME, XhtmlStyleType.class, XhtmlHeadType.class, value);
}
Вот как вы получаете тег <style>
в тег <head>
:
ObjectFactory factory = new ObjectFactory();
XhtmlHtmlType html = factory.createXhtmlHtmlType();
XhtmlHeadType head = factory.createXhtmlHeadType();
html.setHead(head);
XhtmlStyleType style = factory.createXhtmlStyleType();
head.getContent().add(factory.createXhtmlHeadTypeStyle(style));
Первые три использования ObjectFactory
можно считать излишними (хотя и полезными для согласованности), но четвертый делает JAXB намного проще. Imaging должен каждый раз писать new JAXBElement
вручную!
Ответ 2
Как заметил @Chris, иногда JAXB не может работать с POJO, потому что схема не может быть точно сопоставлена с Java. В этих случаях для предоставления дополнительной информации о типе необходимо объекты JAXBElement
.
Есть два конкретных примера, которые я встречал там, где это обычно.
-
Если вы хотите маршалировать объект класса, у которого нет аннотации @XmlRootElement
. По умолчанию XJC генерирует только @XmlRootElement
для некоторых элементов, а не для других. Точная логика для этого немного сложна, но вы можете заставить XJC генерировать больше классов @XmlRootElement
, используя "простой режим привязки"
-
Когда ваша схема использует группы заместителей. Это довольно расширенное использование схемы, но XJC переводит группы подстановки на Java, сильно используя обертки JAXBElement
.
Итак, в XJC-созданной объектной модели, которая сильно использует JAXBElement
(по какой-либо причине), вам нужен способ построения этих экземпляров JAXBElement
. Сгенерированный ObjectFactory
, безусловно, самый простой способ сделать это. Вы можете построить их самостоятельно, но это неудобно и подвержено ошибкам, чтобы сделать это.
Ответ 3
Обратная совместимость, я думаю...
http://weblogs.java.net/blog/kohsuke/archive/2005/08/a_story_of_migr.html:
... Больше нет ObjectFactory.createXYZ. Проблема с этими методами factoryбыло то, что они бросают проверенную JAXBException. Теперь вы можете просто сделать новый XYZ(), больше нет блоков try/catch. (Я знаю, я знаю... это один из тех, "о чем мы думаем!" вещи)...