12

这是一个更普遍的示例问题:我正在使用 xstream 和woodstox,woodstox 在woodstox jar 注册com.ctc.wstx.stax.WstxOutputFactory 中带有javax.xml.stream.XMLOutputFactory 的服务提供程序。我想提供我自己的 javax.xml.stream.XMLOutputFactory 并且在类路径中仍然有woodstox jar。我知道我可以提供自己的系统属性 javax.xml.stream.XMLOutputFactory ,但我正试图从我们的开发运营团队中解脱出来,并使用我的 jar 或我的战争 META 中的服务文件来完成它-INF/服务文件夹。查看 javax.xml.stream.FactoryFinder 的代码如何确保我的 META-INF/services/javax.xml.stream.XMLOutputFactory 文件将是 FactoryFinder 使用的文件?

我们将 xstream 与骆驼一起使用,但找不到将工厂注入 XStreamDataFormat 的方法

4

5 回答 5

8

第一:与其依赖 JDK SPI 接口,我强烈建议简化你的生活而不是使用它。XMLInputFactory与注入和/或您自己相比,它确实没有任何价值XMLOutputFactory。对于注入,您可以使用 Guice(或 Spring);或者只是手动传递。由于这些工厂没有自己的依赖项,因此这很容易。

但是如果选择(或必须)使用XMLInputFactory.newInstance(),您可以为“javax.xml.stream.XMLOutputFactory”和“javax.xml.stream.XMLInputFactory”定义一个系统属性。

那么为什么不使用JDK方法呢?多种原因:

  1. 它增加了开销:如果您没有指定 System 属性,它将不得不扫描整个类路径,并且对于大型应用程序服务器,这需要 10x-100x 的时间,只要大多数解析
  2. 实现的优先级是不确定的:如果你在类路径中有多个,你会得到哪一个?谁知道...(请注意:当您在类路径中添加新 jar 时,它甚至可能会改变)
  3. 您很可能通过传递依赖获得多个 impl

不幸的是,甲骨文似乎仍然坚持添加这种众所周知的错误方法来注册服务提供商。为什么?可能是因为他们没有自己的 DI 库/框架(Guice 来自 google,Spring 来自 Springsource),而且他们往往非常渴望控制。

于 2013-07-23T18:08:22.767 回答
7

您可以这样做来指定要使用的 XMLOutputFactory 实现:

System.setProperty("javax.xml.stream.XMLOutputFactory", ... full classname You want to use ...);

来源: http ://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/1.6/tutorial/doc/SJSXP4.html

从 JAXP 派生的 XMLInputFactory.newInstance() 方法使用以下查找过程确定要加载的特定 XMLInputFactory 实现类:

  1. 使用 javax.xml.stream.XMLInputFactory 系统属性。
  2. 使用 JRE 目录中的 lib/xml.stream.properties 文件。
  3. 使用服务 API(如果可用)通过查看 JRE 可用 jar 中的 META-INF/services/javax.xml.stream.XMLInputFactory 文件来确定类名。
  4. 使用平台默认的 XMLInputFactory 实例。
于 2014-02-28T09:19:26.237 回答
5

我发现如果我将服务文件放在 WEB-INF/classes/services/javax.xml.stream.XMLOutputFactory 下,那么它将位于类路径中,然后在 WEB-INF/lib 中的 jar 之前。这就是我的解决方案。

于 2013-07-23T11:34:56.763 回答
4

我们有类似的问题,解析将在本地运行但在服务器上失败。调试后发现服务器正在使用阅读器com.ctc.wstx.evt.WstxEventReader

而在本地读者是com.sun.xml.internal.stream.XMLEventReaderImpl

我们设置以下属性来解决它。

System.setProperty("javax.xml.stream.XMLInputFactory", "com.sun.xml.internal.stream.XMLInputFactoryImpl");
于 2017-05-10T14:59:57.450 回答
0

如果您的实现在 jar 中,请确保它在类路径上的 woodstox.jar 之前,然后 FactoryFinder 将使用您的实现。

于 2013-07-23T10:32:15.767 回答