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

时间:2013-07-23 10:05:03

标签: java stax serviceloader woodstox service-factory

这是一个更为一般性的问题: 我正在使用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的方法

5 个答案:

答案 0 :(得分:8)

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

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

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

  1. 它增加了开销:如果你没有指定系统属性,它将必须扫描整个类路径,而对于大型应用服务器,这需要10x-100x,只要大多数解析
  2. 实现的优先级是未定义的:如果你在classpath中有多个,你会得到哪一个?谁知道......(注意:当你在类路径中添加新的jar时它甚至可能会改变)
  3. 您很可能通过传递依赖获得多个impl
  4. 不幸的是,Oracle似乎仍然坚持要添加这种已知错误的方法来注册服务提供商。为什么?可能是因为他们没有他们自己的DI lib /框架(Guice是谷歌,Spring by Springsource),他们往往非常控制饥饿。

答案 1 :(得分:6)

你可以这样做来指定你想要使用的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.   
  3. 使用JRE目录中的lib / xml.stream.properties文件。
  4.   
  5. 使用Services API(如果可用)通过查看META-INF / services / javax.xml.stream.XMLInputFactory来确定类名   JRE中可用的罐子中的文件。
  6.   
  7. 使用平台默认的XMLInputFactory实例。
  8.   

答案 2 :(得分:5)

我发现如果我把服务文件放在 WEB-INF / classes / services / javax.xml.stream.XMLOutputFactory然后它将首先在classpath中和WEB-INF / lib中的jars之前。 那是我的解决方案。

答案 3 :(得分:3)

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

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

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

System.setProperty("javax.xml.stream.XMLInputFactory", "com.sun.xml.internal.stream.XMLInputFactoryImpl");

答案 4 :(得分:0)

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