如何在java中覆盖服务提供者

Sha*_*938 10 java stax service-factory woodstox serviceloader

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

我们使用xstream和camel,但找不到将工厂注入XStreamDataFormat的方法

Sta*_*Man 8

第一:我强烈建议您不要依赖JDK SPI接口,而应该简化生活,不要使用它.它确实没有增加注射XMLInputFactory和/或XMLOutputFactory你自己的价值.对于注射,你可以使用Guice(或Spring); 或者只是手动传递它.由于这些工厂没有自己的依赖关系,这很容易.

但是如果选择(或必须)使用XMLInputFactory.newInstance(),则可以为"javax.xml.stream.XMLOutputFactory"和"javax.xml.stream.XMLInputFactory"定义System属性.

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

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

不幸的是,Oracle似乎仍然坚持要为注册服务提供商添加这种已知错误的方法.为什么?可能是因为他们没有自己的DI lib /框架(Guice是google,Spring by Springsource),而且他们倾向于非常控制饥饿.


Rau*_*ets 7

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

System.setProperty("javax.xml.stream.XMLOutputFactory", ... full classname You want to use ...);
Run Code Online (Sandbox Code Playgroud)

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

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

  1. 使用javax.xml.stream.XMLInputFactory系统属性.
  2. 使用JRE目录中的lib/xml.stream.properties文件.
  3. 使用Services API(如果可用)通过查看JRE可用的jar中的META-INF/services/javax.xml.stream.XMLInputFactory文件来确定类名.
  4. 使用平台默认的XMLInputFactory实例.


Sha*_*938 5

我发现,如果我把服务文件下的WEB-INF /班/服务/ javax.xml.stream.XMLOutputFactory那么这将是首次在类路径和WEB-INF/lib目录罐子之前.那是我的解决方案.


Sac*_*apa 5

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

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

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

System.setProperty("javax.xml.stream.XMLInputFactory", "com.sun.xml.internal.stream.XMLInputFactoryImpl");
Run Code Online (Sandbox Code Playgroud)


Evg*_*eev 1

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