Java如何初始化JAXB / JAX-WS / etc实现?

时间:2012-01-01 11:25:30

标签: java jaxb jax-ws

我正在试图理解Java如何在JRE中包含标准参考实现(例如JRE6中的JAXB / JAX-WS),同时仍允许第三方实现覆盖(例如CXF)

我找到了找到javax.xml.ws.spi.FactoryFinder.find()方法的地方,该方法可以找到META-INF / services / java.xml.ws.spi.Provider中指定的类。或com.sun.xml.internal.ws.spi.ProviderImpl(对于JAX-WS案例)并创建该实例。

我找不到的是JRE调用FactoryFinder.find()方法的阶段/位置/在哪个阶段。

任何人都可以启发我吗?

[编辑]我找到了答案,但我不允许自己发布另外3个小时......

4 个答案:

答案 0 :(得分:5)

找出完整的逻辑。实际上JVM启动时没有任何反应。它都基于延迟加载,例如真正的JAX-WS /只在第一次需要时加载/实例化任何提供者。

在加载JAX-WS实现的情况下:

假设我们想要调用一个网络服务,使用以下代码:

MyService     service = new MyService_Service();
MyServiceSoap port    = service.getMyServiceSoap();

port.mymethod(); 

然后发生以下情况以初始化JAX-WS实现:

  • 任何JAX-WS Web服务都扩展了javax.xml.ws.Service,因此MyService_Service扩展了服务
  • 当您创建Web服务的实例时,其超类(javax.xml.ws.Service)也会被初始化(构造函数)
  • “Service”的构造函数调用javax.xml.ws.spi.Provider.provider(),这是一个静态方法,它使用javax.xml.ws.spi.FactoryFinder.find()来查找和实例化实现如配置。

假设我们希望使用以下代码发布

@WebService(endpointInterface = "my.package.MyService")
public class MyServiceImp implements MyService {
    ...
}

MyServiceImp      service  = new MyServiceImp();
InetSocketAddress addr     = new InetSocketAddress(8080);
Executor          executor = Executors.newFixedThreadPool(16);
HttpServer        server   = new HttpServer(addr);
server.setExecutor(executor);

HttpContext       context  = server.createContext("/MyService");
Endpoint          endpoint = Endpoint.create(service);
endpoint.publish(context);
server.start();

然后发生以下情况以初始化JAX-WS实现:

  • Endpoint.create()运行Provider.provider()。createEndpoint()
  • Provider.provider()是一个静态方法,它使用javax.xml.ws.spi.FactoryFinder.find()来查找并实例化已配置的实现。

以下链接帮助我理解了这一点:

答案 1 :(得分:3)

您可以使用系统属性javax.xml.bind.context.factory更改默认行为。它的值应该是工厂的完全限定类名。

此属性的默认值为com.sun.xml.internal.bind.v2.ContextFactory。该工厂不需要实现任何特定接口,因为它必须实现方法createContext(String, ClassLoader, Map)

答案 2 :(得分:2)

有一些机制可以控制您使用的实现。每个jre / jdk都有一个内置的“默认”实现,硬编码到init代码中。您还可以使用一些系统属性来指定特定的实现(如提到的@AlexR)。但是,这不是用于指定不同实现的标准机制。大多数替代实现在其META-INF目录(在jar中)中包含一个特殊文件,它指示jre / jdk应该使用它们而不是默认实现(这可以在不设置任何系统属性的情况下工作,你只需将jar放入classpath)。这些特殊文件由ServiceLoader实用程序找到,可以自动加载备用实现。

答案 3 :(得分:1)

我发现在将一个weblogicfullclient.jar放到类路径后,一个正在运行的JAXB示例失败了,因为jar包含一个META-INF / services / javax.xml.bind.JAXBContext 但不是实施。 不幸的是,人们不能告诉JAXB“只使用PLATFORM_DEFAULT_FACTORY_CLASS”,你必须把它放在一个System属性上(-Djavax.xml.bind.JAXBContext = com.sun.xml.internal.bind.v2.ContextFactory for 1.6 and -Djavax .xml.bind.context.factory = ..对于1.7),javax.xml.bind.ContextFinder.find(String,String,ClassLoader,Map)实现因1.6和1.7而异