Как Java инициализирует реализацию JAXB / JAX-WS / etc? - PullRequest
6 голосов
/ 01 января 2012

Я просто немного копаюсь, пытаясь понять, как в Java могут быть включены стандартные эталонные реализации в JRE (например, JAXB / JAX-WS в JRE6), и в то же время разрешено сторонним реализациям переопределять это (например, 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 ]

5 голосов
/ 01 января 2012

разобрался с полной логикой. На самом деле ничего не происходит при запуске JVM. Все это основано на отложенной загрузке, например, настоящий JAX-WS / любой провайдер загружается / создается только при первой необходимости.

В случае загрузки реализации JAX-WS:

Предположим, мы хотим вызвать веб-сервис, используя такой код:

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

port.mymethod(); 

тогда происходит следующее для инициализации реализации JAX-WS:

  • Любой веб-сервис JAX-WS расширяет javax.xml.ws.Service, поэтому MyService_Service расширяет Сервис
  • Когда вы создаете экземпляр вашего веб-сервиса, его суперкласс (javax.xml.ws.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 () для поиска и создания экземпляра реализации в соответствии с настройкой.

Следующие ссылки помогли мне понять это:

3 голосов
/ 01 января 2012

Вы можете изменить поведение по умолчанию, используя системное свойство javax.xml.bind.context.factory.Его значением должно быть полное имя класса фабрики.

Значение этого свойства по умолчанию: com.sun.xml.internal.bind.v2.ContextFactory.Эта фабрика не обязана реализовывать какой-либо конкретный интерфейс, она должна реализовывать метод createContext(String, ClassLoader, Map)

2 голосов
/ 01 января 2012

Есть несколько механизмов, которые контролируют, какую реализацию вы используете. каждый jre / jdk имеет встроенную реализацию по умолчанию, жестко запрограммированную в коде инициализации. Есть также некоторые системные свойства, которые вы можете использовать для указания конкретной реализации (как упоминалось @AlexR). однако это не стандартный механизм для указания другой реализации. большинство альтернативных реализаций содержат специальный файл в своем каталоге META-INF (внутри jar), который указывает jre / jdk, что их следует использовать вместо реализации по умолчанию (это работает без установки каких-либо системных свойств, вы просто отбрасываете jar в путь к классам). Эти специальные файлы находятся утилитой ServiceLoader и позволяют автоматически загружать альтернативную реализацию.

1 голос
/ 26 сентября 2013

Я обнаружил, что рабочий образец JAXB завершается неудачно после помещения файла weblogicfullclient.jar в путь к классам, потому что файл jar содержит META-INF / services / javax.xml.bind.JAXBContext, но не реализацию.К сожалению, нельзя сказать JAXB «просто использовать PLATFORM_DEFAULT_FACTORY_CLASS», вы должны поместить его в системное свойство (-Djavax.xml.bind.JAXBContext = com.sun.xml.internal.bind.v2.ContextFactory для 1.6 и -Djavax.xml.bind.context.factory = .. для 1.7), реализации javax.xml.bind.ContextFinder.find (String, String, ClassLoader, Map) различаются для 1.6 и 1.7

.
...