Использование Java classpath для выполнения Java 9+ Services - PullRequest
0 голосов
/ 12 октября 2019

Я создал простой пример сервиса Java9 с одним интерфейсом сервиса и двумя реализациями сервиса и одним драйвером, который использует ServiceLoader. Мне удалось успешно выполнить пример с модулем-путем, но когда я попытался выполнить то же самое с помощью java -cp (classpath), я не получил никакого вывода, даже никакой ошибки.

Структура каталогов

out
├── driver
│   ├── com
│   │   └── company
│   │       └── driver
│   │           └── driver.class
│   └── module-info.class
├── firstServiceImpl
│   ├── com
│   │   └── company
│   │       └── first
│   │           └── serviceImpl
│   │               └── FunImpl1.class
│   └── module-info.class
├── secondServiceImpl
│   ├── com
│   │   └── company
│   │       └── second
│   │           └── serviceImpl
│   │               └── FunImpl2.class
│   └── module-info.class
└── serviceInterface
    ├── com
    │   └── company
    │       └── service
    │           └── Fun.class
    └── module-info.class

команда для компиляции

javac -d out --module-source-path src src/driver/driver.java src/firstServiceImpl/FunImpl1.java src/secondServiceImpl/FunImpl2.java src/serviceInterface/Fun.java

Приведенная выше команда компилирует код с module-source-path .

команда для запуска

java -cp out/driver:out/serviceInterface/:out/firstServiceImpl/ com.sunil.driver.driver

Приведенная выше команда запускает код с classpath .

После компиляции с модулем -source-path и запустить код с classpath . Я не получаю никакой ошибки или вывода. Пожалуйста, помогите мне понять, почему при запуске с использованием classpath .

нет выходных данных.

1 Ответ

1 голос
/ 12 октября 2019

Расположение поставщиков услуг зависит от того, находятся ли поставщики услуг на пути к классам или на модуле. Это описано в документации ServiceLoader:

Развертывание поставщиков услуг в виде модулей

Поставщик услуг, разработанный в модуле, должен быть указан в предоставляет директиву в объявлении модуля. Директива обеспечивает указание как службы, так и поставщика услуг;это помогает найти провайдера, когда другой модуль с использует директиву для службы, получает загрузчик службы для службы. Настоятельно рекомендуется, чтобы модуль не экспортировал пакет, содержащий поставщика услуг. Модуль не поддерживает указание в директиве поставщика поставщика услуг в другом модуле.

[...]

Развертывание поставщиков услуг в классепуть

Поставщик услуг, который упакован как файл JAR для пути к классу, определяется путем помещения файла конфигурации поставщика в каталог ресурсов META-INF/services. Имя файла конфигурации провайдера - это полное двоичное имя службы. Файл конфигурации провайдера содержит список полностью определенных двоичных имен поставщиков услуг, по одному на строку.

[...]

По сути, если вы хотите иметь возможностьзагрузить поставщика услуг независимо от того, находится ли он в classpath или modulepath, вам нужно будет указать обе директивы provides в файле module-info.java и добавить соответствующий файл конфигурации поставщика в META-INF/services. Вы также должны убедиться, что используете правильный способ загрузки поставщиков услуг:

  • ServiceLoader#load(Class,ClassLoader)

    • Находит поставщиковв именованных модулях (т. е. modulepath) и неназванных модулях (т. е. classpath).
  • ServiceLoader#load(ModuleLayer,Class)

    • Только обнаруживает местоположениепровайдеры в именованных модулях (т.е. modulepath).
...