2009-06-05 3 views
81

Я новичок в использовании JAXB, и я использовал xjc JAXB 2.1.3 для создания набора классов из моей XML-схемы. Помимо создания класса для каждого элемента в моей схеме, он создал класс ObjectFactory.В чем смысл классов ObjectFactory JAXB 2?

Кажется, что ничего не мешает мне создавать элементы непосредственно, например.

MyElement element = new MyElement(); 

в то время как учебники, кажется, предпочитают

MyElement element = new ObjectFactory().createMyElement(); 

Если я смотрю в ObjectFactory.java, я вижу:

public MyElement createMyElement() { 
    return new MyElement(); 
} 

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

ответ

56

Обратная совместимость не единственная причина. :-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 намного, намного проще в использовании. При визуальном оформлении необходимо вручную выписать new JAXBElement вручную!

+0

Можете ли вы привести пример/ссылку на то, что (или насколько сложно) элемент схемы должен быть для того, чтобы создать *(), чтобы сделать что-то полезное? У меня возникли проблемы с поиском части схемы, на которую вы ссылаетесь на примере JAXB. Если моя схема будет более сложной позже, было бы неплохо создать * для обработки ее части для меня, но поскольку она создаёт *, даже не нужно создавать подэлементы самостоятельно. –

+0

Если вы загружаете XHTML 1.1 и XHTML Modularization 1.1 tarballs, вы найдете каталоги внутри под названием «SCHEMA». Поместите все файлы .xsd в одни и те же каталоги. Некоторые из файлов .xsd также будут импортированы http://www.w3.org/2001/xml.xsd; вам нужно будет соответствующим образом скорректировать расположение, если вы не хотите, чтобы файл загружался каждый раз при запуске xjc. [cont] –

+0

[cont] Конкретная часть .xsd, которая указывает содержимое , в этом случае находится в xhtml11-model-1.xsd, в группе xhtml.head.content. –

8

обратной совместимости, я думаю ...

http://weblogs.java.net/blog/kohsuke/archive/2005/08/a_story_of_migr.html:

... Нет больше ObjectFactory.createXYZ. Проблема с этими заводскими методами состояла в том, что они выбрасывают проверенное исключение JAXBException . Теперь вы можете просто сделать новых XYZ(), больше не пытаться/блокировать блоки. (я знаю, я знаю, ... это один из тех, «что мы думали !?» вещей) ...

34

Как отметил @Chris, иногда JAXB не может работать с POJO, потому что схема не может быть точно сопоставлена ​​с Java. В этих случаях для предоставления дополнительной информации о типе необходимы объекты оболочки JAXBElement.

Есть два конкретных примера, с которыми я столкнулся, где это распространено.

  • Если вы хотите, чтобы мобилизовывать объект класса, который не имеет в @XmlRootElement аннотацию. По умолчанию XJC генерирует только @XmlRootElement для некоторых элементов, а не для других.Точная логика для этого немного сложна, но вы можете заставить XJC генерировать больше классов @XmlRootElement, используя "simple binding mode"

  • Когда ваша схема использует группы заместителей. Это довольно продвинутое использование схемы, но XJC переводит группы замещения в Java, сильно применяя обертки JAXBElement.

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

+0

Спасибо за дополнительные примеры! –

+2

Вау, это победный ответ. +1 –

+2

Это тоже на 3 месяца :) – skaffman