JAXB 2的ObjectFactory类有什么意义?


98

我是使用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类?我假设如果我从更改后的模式重新编译,它也会被覆盖。


我不确定它是否是预期的设计,但是我发现ObjectFactory是创建JAXBContext的理想类。您需要在此处枚举一些类,并且JAXB将遵循它们的方法,依此类推,因此它们就像是根。而且ObjectFactory引用了所有元素,因此仅使用ObjectFactory.class来创建具有所有相关类的JAXBContext就足够了。
vbezhenar

Answers:


68

向后兼容性不是唯一原因。:-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每次都要手工写出!


您能否举例/说明Schema元素需要什么(或多么复杂)才能使create *()做一些有用的事情?我在查找使用JAXB示例引用的Schema部分时遇到了麻烦。如果我的模式变得更加复杂之后,它肯定会是很好的创造*处理的一部分,对我来说,因为它是建立*根本不屑自行创建的子元素..
安德鲁Coleson

如果下载XHTML 1.1和XHTML Modularization 1.1压缩包,则将在内部找到名为“ SCHEMA”的目录。将所有.xsd文件放在同一目录中。一些.xsd文件还将导入w3.org/2001/xml.xsd;如果您不想每次运行xjc时都下载文件,则需要适当地调整位置。[续]
克里斯·杰斯特·杨

[续]在这种情况下,指定<head>内容的.xsd的特定部分在xhtml11-model-1.xsd中的xhtml.head.content组下。
克里斯·杰斯特·杨

2
无论如何,没有人用枪指着您说必须使用ObjectFactory(尽管我发现使用起来很方便),但是当您遇到真正有用的情况时,您会知道的。:-)
克里斯·杰斯特·杨

谢谢!我想我的架构还不够复杂,但是我会在未来牢记这一点。:)我知道我必须丢失一些东西。
Andrew Coleson

39

正如@Chris指出的那样,有时JAXB不能与POJO一起使用,因为该模式无法准确地映射到Java。在这些情况下,JAXBElement包装器对象对于提供附加的类型信息是必需的。

在常见的地方,我遇到了两个具体的例子。

  • 如果要封送没有@XmlRootElement注释的类的对象。默认情况下,XJC仅为@XmlRootElement某些元素生成,而不为其他元素生成。确切的逻辑有点复杂,但是您可以@XmlRootElement使用“简单绑定模式”强制XJC生成更多的类。

  • 当您的架构使用替代组时。这是相当高级的模式用法,但是XJC通过大量使用JAXBElement包装器将替换组转换为Java 。

因此,在XJC生成的对象模型大量使用JAXBElement(无论出于何种原因)中,您需要一种构造这些JAXBElement实例的方法。ObjectFactory到目前为止,生成是最简单的方法。您可以自己构建它们,但是这样做很麻烦且容易出错。


感谢您的其他示例!
Andrew Coleson

2
哇,这是一个成功的答案。+1
克里斯·杰斯特·杨

我喜欢使用annox在95%的时间内生成XmlRootElement,如果我有一个指向complexType的elememtn,我想要XmlRootElement(嗯,更像是100%,因为我还没有碰到我不想要的用例还没有)
迪恩·希勒

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.