【问题标题】:What's the point of JAXB 2's ObjectFactory classes?JAXB 2 的 ObjectFactory 类有什么意义?
【发布时间】:2010-10-31 12:33:15
【问题描述】:

我是使用 JAXB 的新手,我使用 JAXB 2.1.3 的 xjc 从我的 XML Schema 生成一组类。除了为我的架构中的每个元素生成一个类之外,它还创建了一个 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 就足够了。

标签: java jaxb


【解决方案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);
}

这就是您将&lt;style&gt; 标记转换为&lt;head&gt; 标记的方法:

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 变得更复杂,create* 为我处理其中的一部分当然会很好,但由于它是 create* 甚至不会费心自己创建子元素..
  • 如果您下载 XHTML 1.1 和 XHTML Modularization 1.1 压缩包,您会在里面找到名为“SCHEMA”的目录。将所有 .xsd 文件放在相同的目录中。一些 .xsd 文件也会导入w3.org/2001/xml.xsd;如果您不希望每次运行 xjc 时都下载文件,则需要适当地调整位置。 [续]
  • [cont] .xsd 中指定 内容的特定部分,在这种情况下,在 xhtml11-model-1.xsd 中,位于 xhtml.head.content 组下.
  • 无论如何,没有人用枪指着你的头说你必须使用 ObjectFactory(虽然我觉得它很方便),但是当你遇到真正有用的情况时,你就会知道它。 :-)
  • 谢谢!我想我的架构还不够复杂,但我会记住它以备将来使用。 :) 我知道我必须遗漏一些东西。
【解决方案2】:

正如@Chris 所指出的,有时 JAXB 无法与 POJO 一起使用,因为架构无法准确映射到 Java。在这些情况下,JAXBElement 包装器对象对于提供额外的类型信息是必要的。

我遇到了两个常见的具体示例。

  • 如果要编组一个没有@XmlRootElement 注释的类的对象。默认情况下,XJC 只为某些元素生成@XmlRootElement,而不为其他元素生成。确切的逻辑有点复杂,但您可以强制 XJC 使用 "simple binding mode" 生成更多 @XmlRootElement

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

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

【讨论】:

  • 感谢您提供更多示例!
  • 哇,这是一个成功的答案。 +1
  • 我喜欢使用 annox 来生成 XmlRootElement,如果我有一个引用 complexType 的 elememtn,我想要 XmlRootElement(好吧,更像是 100%,因为我没有点击我不想要的用例)
【解决方案3】:

向后兼容性,我猜...

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

...不再有 ObjectFactory.createXYZ。 那些工厂方法的问题 是他们扔了一个检查 JAXB 异常。现在你可以简单地做 新的 XYZ(),不再有 try/catch 块。 (我知道,我知道,......这是其中之一 那些“我们在想什么!?” 东西)...

【讨论】:

    猜你喜欢
    • 2011-09-20
    • 2012-11-16
    • 2010-11-28
    • 2020-05-26
    • 2015-04-27
    • 1970-01-01
    • 2011-02-09
    • 2012-03-22
    相关资源
    最近更新 更多