Класс ServiceLoader<S>
- Параметры типа:
-
S- Тип службы, которая должна быть загружена этим загрузчиком
- Все реализованные интерфейсы:
Iterable<S>
public final class ServiceLoader<S> extends Object implements Iterable<S>
Сервис — это широко известный интерфейс или класс, для которого существуют ноль, один или несколько поставщиков сервисов. Поставщик сервиса (или просто поставщик) — это класс, реализующий или наследующий широко известный интерфейс или класс. ServiceLoader — это объект, который находит и загружает поставщиков сервисов, развернутых в среде выполнения в момент, выбранный приложением. Код приложения ссылается только на сервис, а не на поставщиков сервиса, и предполагается, что он может выбирать между несколькими поставщиками сервиса (в зависимости от функциональности, которую они предоставляют через сервис) и обрабатывать возможность отсутствия поставщиков сервиса.
Получение загрузчика сервиса
Приложение получает загрузчик сервиса для данного сервиса, вызывая один из статических load методов ServiceLoader. Если приложение является модулем, то его описание модуля должно содержать директиву uses, которая указывает сервис; это помогает определить поставщиков и гарантирует их надежную работу. Кроме того, если модуль приложения не содержит сервис, то его описание модуля должно содержать директиву requires, которая указывает модуль, экспортирующий сервис. Сильно рекомендуется, чтобы модуль приложения не требовал модулей, содержащих поставщиков сервиса.
Загрузчик сервиса может быть использован для поиска и создания экземпляров поставщиков сервиса с помощью метода iterator. ServiceLoader также определяет метод stream для получения потока поставщиков, которые можно просматривать и фильтровать без создания экземпляров.
Например, предположим, что сервис — это com.example.CodecFactory, интерфейс, определяющий методы для создания кодеров и декодеров:
package com.example;
public interface CodecFactory {
Encoder getEncoder(String encodingName);
Decoder getDecoder(String encodingName);
}
Следующий код получает загрузчик сервиса для сервиса CodecFactory, а затем использует его итератор (автоматически созданный расширенным циклом for), чтобы получать экземпляры поставщиков сервиса, которые были найдены:
ServiceLoader<CodecFactory> loader = ServiceLoader.load(CodecFactory.class);
for (CodecFactory factory : loader) {
Encoder enc = factory.getEncoder("PNG");
if (enc != null)
... use enc to encode a PNG file
break;
}
Если этот код находится в модуле, то для ссылки на интерфейс com.example.CodecFactory модуль должен потребовать модуль, экспортирующий интерфейс. Описание модуля также должно указать использование com.example.CodecFactory:
requires com.example.codec.core;
uses com.example.CodecFactory;
Иногда приложение может захотеть проверить поставщика сервиса перед созданием экземпляра, чтобы определить, будет ли экземпляр этого поставщика полезен. Например, поставщик сервиса для
CodecFactory, способный создавать кодер "PNG", может быть аннотирован @PNG. Следующий код использует метод загрузчика сервиса stream для получения экземпляров Provider<CodecFactory> в отличие от того, как итератор возвращает экземпляры CodecFactory:
ServiceLoader<CodecFactory> loader = ServiceLoader.load(CodecFactory.class);
Set<CodecFactory> pngFactories = loader
.stream() // Note a below
.filter(p -> p.type().isAnnotationPresent(PNG.class)) // Note b
.map(Provider::get) // Note c
.collect(Collectors.toSet());
- Поток объектов
Provider<CodecFactory> -
p.type()возвращаетClass<CodecFactory> -
get()возвращает экземплярCodecFactory
Разработка сервисов
Сервис — это единый тип, обычно интерфейс или абстрактный класс. Может быть использован конкретный класс, но это не рекомендуется. Тип может иметь любую видимость. Методы сервиса очень специфичны для конкретной предметной области, поэтому это описание API не может дать конкретных рекомендаций о форме или функции. Однако есть два общих руководства:
Сервис должен объявлять столько методов, сколько необходимо, чтобы позволить поставщикам сервиса передавать свойства, специфичные для предметной области, и другие факторы качества реализации. Приложение, которое получает загрузчик сервиса для сервиса, может затем вызывать эти методы для каждого экземпляра поставщика сервиса, чтобы выбрать наилучшего поставщика для приложения.
Сервис должен указывать, предназначены ли его поставщики сервиса для прямой реализации сервиса или для механизма косвенного обращения, такого как "прокси" или "фабрика". Поставщики сервиса обычно являются механизмами косвенного обращения, когда объекты предметной области относительно дорого создаются; в этом случае сервис должен быть разработан таким образом, чтобы поставщики сервиса были абстракциями, создающими "реальную" реализацию по требованию. Например, сервис
CodecFactoryвыражает через свое имя, что его поставщики сервиса являются фабриками для кодеров, а не самими кодерами, поскольку создание определенных кодеров может быть дорогим или сложным.
Разработка поставщиков сервиса
Поставщик сервиса — это единый тип, обычно конкретный класс. Разрешается использовать интерфейс или абстрактный класс, так как он может объявлять статический метод поставщика, который обсуждается позже. Тип должен быть публичным и не должен быть внутренним классом.
Поставщик сервиса и его вспомогательный код могут быть разработаны в модуле, который затем развертывается в пути модуля приложения или в модульном изображении. В качестве альтернативы поставщик сервиса и его вспомогательный код могут быть упакованы в файл JAR и развернуты на пути класса приложения. Преимущество разработки поставщика сервиса в модуле заключается в том, что поставщик может быть полностью инкапсулирован, чтобы скрыть все детали его реализации.
Приложение, которое получает загрузчик сервиса для заданного сервиса, не обращает внимания на то, развернуты ли поставщики сервиса в модулях или упакованы в файлы JAR. Приложение создает экземпляры поставщиков сервиса с помощью итератора загрузчика сервиса или объектов Provider в потоке загрузчика сервиса без знания местоположения поставщиков сервиса.
Развертывание поставщиков сервиса как модулей
Поставщик сервиса, разработанный в модуле, должен быть указан в директиве provides в описании модуля. Директива provides указывает как сервис, так и поставщика сервиса; это помогает найти поставщика, когда другой модуль с директивой uses для сервиса получает загрузчик сервиса для сервиса. Сильно рекомендуется, чтобы модуль не экспортировал пакет, содержащий поставщика сервиса. Не поддерживается указание в директиве provides модуля поставщика сервиса в другом модуле.
Поставщик сервиса, разработанный в модуле, не контролирует время его создания, поскольку это происходит по желанию приложения, но контролирует способ его создания:
- Если поставщик сервиса объявляет метод поставщика, то загрузчик сервиса вызывает этот метод для получения экземпляра поставщика сервиса. Метод поставщика — это публичный статический метод с именем "provider" без формальных параметров и типом возвращаемого значения, присваиваемым интерфейсу или классу сервиса.
В этом случае сам поставщик сервиса не обязательно должен быть присваиваем интерфейсу или классу сервиса.
- Если поставщик сервиса не объявляет метод поставщика, то поставщик сервиса создается напрямую через его конструктор поставщика. Конструктор поставщика — это публичный конструктор без формальных параметров.
В этом случае поставщик сервиса должен быть присваиваем интерфейсу или классу сервиса.
Поставщик сервиса, развернутый как автоматический модуль на пути модуля приложения, должен иметь конструктор поставщика. Метод поставщика в этом случае не поддерживается.
Например, предположим, что модуль указывает следующую директиву:
provides com.example.CodecFactory with com.example.impl.StandardCodecs,
com.example.impl.ExtendedCodecsFactory;
где
-
com.example.CodecFactory— это сервис с двумя методами из предыдущего примера. -
com.example.impl.StandardCodecs— это публичный класс, реализующийCodecFactoryи имеющий публичный конструктор без аргументов. -
com.example.impl.ExtendedCodecsFactory— это публичный класс, не реализующий CodecFactory, но объявляющий публичный статический метод без аргументов с именем "provider" и типом возвращаемого значенияCodecFactory.
Загрузчик сервиса создаст экземпляр StandardCodecs через его конструктор и создаст экземпляр ExtendedCodecsFactory, вызвав его метод provider. Требование, чтобы конструктор поставщика или метод поставщика был публичным, помогает документировать намерение, что класс (то есть поставщик сервиса) будет создан сущностью (то есть загрузчиком сервиса), которая находится вне пакета класса.
Размещение поставщиков сервиса на пути класса
Поставщик сервиса, упакованный в файл JAR для пути класса, определяется путем размещения файла конфигурации поставщика в каталоге ресурсовMETA-INF/services. Имя файла конфигурации поставщика — это полное двоичное имя сервиса. Файл конфигурации поставщика содержит список полных двоичных имен поставщиков сервиса, по одному на строку. Например, предположим, что поставщик сервиса com.example.impl.StandardCodecs упакован в файл JAR для пути класса. Файл JAR будет содержать файл конфигурации поставщика с именем:
META-INF/services/com.example.CodecFactory
который содержит строку:
com.example.impl.StandardCodecs # Standard codecs
Файл конфигурации поставщика должен быть закодирован в UTF-8. Пробелы и символы табуляции вокруг имени каждого поставщика сервиса, а также пустые строки игнорируются. Символ комментария — '#' (U+0023 ДИЕЗ); в каждой строке все символы после первого символа комментария игнорируются. Если имя класса поставщика сервиса указано в файле конфигурации поставщика более одного раза, дубликат игнорируется. Если имя класса поставщика сервиса указано в нескольких файлах конфигурации, дубликат игнорируется.
Поставщик сервиса, упомянутый в файле конфигурации поставщика, может находиться в том же файле JAR, что и файл конфигурации поставщика, или в другом файле JAR. Поставщик сервиса должен быть видим из загрузчика классов, который изначально запрашивается для поиска файла конфигурации поставщика; это не обязательно загрузчик классов, который в конечном итоге находит файл конфигурации поставщика.
Время обнаружения поставщиков
Поставщики сервиса загружаются и создаются лениво, то есть по требованию. Загрузчик сервиса сохраняет кэш загруженных поставщиков. Каждый вызов метода iterator возвращает итератор, который сначала возвращает все элементы, кэшированные из предыдущей итерации в порядке создания экземпляров, а затем лениво находит и создает любые оставшиеся поставщики, добавляя каждый из них в кэш по очереди. Аналогично, каждый вызов метода потока возвращает поток, который сначала обрабатывает все поставщики, загруженные предыдущими операциями потока, в порядке загрузки, а затем лениво находит любые оставшиеся поставщики. Кэши очищаются с помощью метода reload.
Ошибки
При использовании загрузчика сервисов iterator, методы hasNext и next завершатся ошибкой ServiceConfigurationError, если произойдет ошибка при поиске, загрузке или инициализации поставщика сервиса. При обработке потока загрузчика сервисов, ServiceConfigurationError может быть выброшено любым методом, вызывающим поиск или загрузку поставщика сервиса.
При загрузке или инициализации поставщика сервиса в модуле,
ServiceConfigurationError может быть выброшено по следующим причинам:
- Поставщик сервиса не может быть загружен.
- Поставщик сервиса не объявляет метод поставщика, и его нельзя присвоить интерфейсу/классу сервиса, или у него нет конструктора поставщика.
- Поставщик сервиса объявляет публичный статический метод без аргументов с именем "provider" и типом возвращаемого значения, который нельзя присвоить интерфейсу или классу сервиса.
- Файл класса поставщика сервиса содержит более одного публичного статического метода без аргументов с именем "
provider". - Поставщик сервиса объявляет метод поставщика, и он завершается неудачно, возвращая
nullили выбрасывая исключение. - Поставщик сервиса не объявляет метод поставщика, и его конструктор поставщика завершается неудачно, выбросив исключение.
При чтении файла конфигурации поставщика или загрузке или инициализации класса поставщика, указанного в файле конфигурации поставщика, может быть выброшено
ServiceConfigurationError по следующим причинам:
- Формат файла конфигурации поставщика нарушает формат, указанный выше;
- При чтении файла конфигурации поставщика происходит
IOException; - Поставщик сервиса не может быть загружен;
- Поставщик сервиса не может быть присвоен интерфейсу или классу сервиса, не определяет конструктор поставщика или не может быть инициирован.
Безопасность
Загрузчики сервисов всегда выполняются в контексте безопасности вызывающего метода итератора или метода потока, а также могут быть ограничены контекстом безопасности вызывающего, который создал загрузчик сервиса. Доверенный системный код обычно должен вызывать методы этого класса и методы итераторов, которые они возвращают, внутри привилегированного контекста безопасности.
Конкурентность
Экземпляры этого класса не являются потокобезопасными.
Обработка null
Если не указано иное, передача null аргумента в любой метод этого класса приведет к выбросу NullPointerException.
- Since:
- 1.6
Краткое описание вложенных классов
| Модификатор и тип | Класс | Описание |
|---|---|---|
static interface |
ServiceLoader.Provider<S> |
Представляет поставщика сервиса, найденного с помощью ServiceLoader. |
Краткое описание методов
| Модификатор и тип | Метод | Описание |
|---|---|---|
Optional |
findFirst() |
Загружает первый доступный поставщик сервиса для сервиса этого загрузчика. |
Iterator |
iterator() |
Возвращает итератор для ленивой загрузки и инициализации доступных поставщиков сервиса этого загрузчика. |
static <S> ServiceLoader |
load |
Создает новый загрузчик сервисов для заданного типа сервиса, используя контекстный загрузчик класса текущей нити. |
static <S> ServiceLoader |
load |
Создает новый загрузчик сервисов для заданного сервиса. |
static <S> ServiceLoader |
load |
Создает новый загрузчик сервисов для заданного типа сервиса, чтобы загрузить поставщиков сервисов из модулей в заданном слое модулей и его предков. |
static <S> ServiceLoader |
loadInstalled |
Создает новый загрузчик сервисов для заданного типа сервиса, используя платформенный загрузчик классов. |
void |
reload() |
Очищает кэш поставщиков этого загрузчика, чтобы все поставщики были перезагружены. |
Stream |
stream() |
Возвращает поток для ленивой загрузки доступных поставщиков сервиса этого загрузчика. |
String |
toString() |
Возвращает строку, описывающую этот сервис. |
Методы, унаследованные от класса java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
Методы, унаследованные от интерфейса java.lang.Iterable
forEach, spliterator
Подробное описание методов
iterator
public Iterator<S> iterator()
Для достижения ленивой загрузки фактическая работа по поиску и созданию поставщиков выполняется самим итератором. Его методы hasNext и next могут, следовательно, выбросить исключение ServiceConfigurationError по любой из причин, указанных в разделе Ошибки выше. Для написания надёжного кода достаточно перехватить ServiceConfigurationError при использовании итератора. Если возникает ошибка, последующие вызовы итератора предпримут все возможные усилия для поиска и создания следующего доступного поставщика, но в целом такая реставрация не гарантируется.
Кэширование: Итератор, возвращённый этим методом, сначала возвращает все элементы кэша поставщиков в порядке их загрузки. Затем он лениво загружает и создаёт оставшихся поставщиков сервиса, добавляя каждый из них в кэш по очереди. Если кэши поставщиков этого загрузчика очищаются с помощью метода reload, то существующие итераторы для этого загрузчика сервиса должны быть удалены. Методы hasNext и next итератора выбрасывают исключение ConcurrentModificationException, если используются после очистки кэша поставщиков.
Возвращённый этим методом итератор не поддерживает удаление. Вызов его метода remove вызовет исключение UnsupportedOperationException.
- Определено в:
-
iteratorв интерфейсеIterable<S> - Примечание API:
- Выбрасывание ошибки в этих случаях может показаться крайним. Обоснование такого поведения заключается в том, что некорректный файл конфигурации поставщика, как и некорректный файл класса, указывает на серьёзную проблему с конфигурацией или использованием виртуальной машины Java. Поэтому предпочтительнее выбросить ошибку, чем пытаться восстановиться или, что ещё хуже, проигнорировать её.
- Возвращает:
- Итератор, который лениво загружает поставщиков для сервиса этого загрузчика
stream
public Stream<ServiceLoader.Provider<S>> stream()
Provider, необходимо вызвать метод get поставщика, чтобы получить или создать его. Для достижения ленивой загрузки фактическая работа по поиску поставщиков выполняется при обработке потока. Если поставщик сервиса не может быть загружен по любой из причин, указанных в разделе Ошибки выше, то исключение ServiceConfigurationError выбрасывается методом, вызвавшим загрузку поставщика.
Кэширование: При обработке потока сначала обрабатываются поставщики, которые были ранее загружены операциями с потоком, в порядке загрузки. Затем лениво загружаются все оставшиеся поставщики сервиса. Если кэши поставщиков этого загрузчика очищаются путём вызова метода reload, то существующие потоки для этого загрузчика сервиса должны быть удалены. Источник возвращаемого потока spliterator является быстродействующим и выбросит исключение ConcurrentModificationException, если кэш поставщиков был очищен.
Следующие примеры демонстрируют использование. Первый пример создаёт поток объектов CodecFactory, второй пример такой же, за исключением того, что он сортирует поставщиков по имени класса поставщика (и, таким образом, находит всех поставщиков).
Stream<CodecFactory> providers = ServiceLoader.load(CodecFactory.class)
.stream()
.map(Provider::get);
Stream<CodecFactory> providers = ServiceLoader.load(CodecFactory.class)
.stream()
.sorted(Comparator.comparing(p -> p.type().getName()))
.map(Provider::get);
- Возвращает:
- Поток, который лениво загружает поставщиков для сервиса этого загрузчика
- С:
- 9
load
public static <S> ServiceLoader<S> load(Class<S> service, ClassLoader loader)
iterator и stream находит поставщиков как в именованных, так и в безымянных модулях следующим образом: -
Шаг 1: Поиск поставщиков в именованных модулях.
Поставщики сервисов ищутся во всех именованных модулях загрузчика классов или в любом загрузчике классов, доступном через делегирование родителя.
Кроме того, если загрузчик классов не является загрузчиком Bootstrap или платформенным загрузчиком классов, то поставщики сервисов могут быть найдены в именованных модулях других загрузчиков классов. В частности, если загрузчик классов или любой загрузчик классов, доступный через делегирование родителя, имеет модуль в слое модулей, то поставщики сервисов во всех модулях в слое модулей ищутся.
Например, предположим, что существует слой модулей, где каждый модуль находится в собственном загрузчике классов (см.
defineModulesWithManyLoaders). Если этот методServiceLoader.loadвызывается для поиска поставщиков, используя любой из загрузчиков классов, созданных для слоя модулей, то он найдёт всех поставщиков в слое модулей, независимо от их определяющего загрузчика классов.Порядок: загрузчик сервиса сначала ищет поставщиков сервиса в модулях, определённых для загрузчика классов, затем в его родительском загрузчике классов, в его родительском родителе и так далее до загрузчика Bootstrap. Если у загрузчика классов есть модули в слое модулей, то все поставщики в этом слое модулей ищутся (независимо от их загрузчика классов) перед поставщиками в родительском загрузчике классов. Порядок модулей в том же загрузчике классов или порядок модулей в слое модулей не определён.
Если модуль объявляет более одного поставщика, то поставщики ищутся в порядке, в котором их перечисляет дескриптор модуля в списке поставщиков. Поставщики, добавленные динамически агентами инструментов (см.
redefineModule) всегда находятся после поставщиков, объявленных модулем. -
Шаг 2: Поиск поставщиков в безымянных модулях.
Поставщики сервисов в безымянных модулях ищутся, если их имена классов указаны в файлах конфигурации поставщиков, находящихся по пути, указанному методом загрузчика классов
getResources.Порядок основан на порядке, в котором метод
getResourcesзагрузчика классов находит файлы конфигурации сервиса, и в пределах этого порядка, на порядке, в котором имена классов перечислены в файле.Любое упоминание о поставщике сервиса, развернутом в именованном модуле, игнорируется в файле конфигурации поставщика. Это сделано для предотвращения дублирования, которое в противном случае возникнет, когда именованный модуль имеет как директиву provides, так и файл конфигурации поставщика, упоминающий того же поставщика сервиса.
Класс поставщика должен быть видимым для загрузчика классов.
- Примечание API:
- Если путь к классу загрузчика классов включает удалённые сетевые URL-адреса, то эти URL-адреса могут быть обработаны при поиске файлов конфигурации поставщиков.
Эта активность нормальна, хотя она может создавать непонятные записи в журналах веб-сервера. Однако, если веб-сервер не настроен должным образом, то эта активность может привести к непредсказуемому сбою алгоритма загрузки поставщиков.
Веб-сервер должен возвращать ответ HTTP 404 (Не найдено), когда запрашиваемого ресурса не существует. Иногда, однако, веб-серверы ошибочно настраиваются так, чтобы возвращать ответ HTTP 200 (OK) вместе с полезной страницей ошибки HTML в таких случаях. Это приведёт к выбросу исключения
ServiceConfigurationErrorпри попытке этого класса разобрать страницу HTML как файл конфигурации поставщика. Лучшим решением этой проблемы является исправление неправильно настроенного веб-сервера, чтобы он возвращал правильный код ответа (HTTP 404) вместе со страницей ошибки HTML. - Параметры типа:
-
S- класс типа сервиса - Параметры:
-
service- Интерфейс или абстрактный класс, представляющий сервис -
loader- Загрузчик классов, который будет использоваться для загрузки файлов конфигурации поставщиков и классов поставщиков, илиnull, если следует использовать системный загрузчик классов (или, в противном случае, загрузчик Bootstrap) - Возвращает:
- Новый загрузчик сервиса
- Исключения:
-
ServiceConfigurationError- если тип сервиса недоступен для вызывающего объекта или вызывающий объект находится в явном модуле, а дескриптор его модуля не объявляет, что он используетservice
load
public static <S> ServiceLoader<S> load(Class<S> service)
Вызов этого вспомогательного метода в форме
ServiceLoader.load(service)
эквивалентен
ServiceLoader.load(service, Thread.currentThread().getContextClassLoader())
- Примечание API:
- Объекты загрузчика сервиса, полученные с помощью этого метода, не должны кэшироваться на уровне всей виртуальной машины. Например, разные приложения в одной виртуальной машине могут иметь разные контекстные загрузчики классов потока. Поиск одним приложением может найти поставщика сервиса, который виден только через контекстный загрузчик класса потока и поэтому не подходит для поиска другим приложением. Также могут возникнуть утечки памяти. Для некоторых приложений может подойти использование потоковой локальной переменной.
- Параметры типа:
-
S- класс типа сервиса - Параметры:
-
service- Интерфейс или абстрактный класс, представляющий сервис - Возвращает:
- Новый загрузчик сервиса
- Исключения:
-
ServiceConfigurationError- если тип сервиса недоступен для вызывающего объекта или вызывающий объект находится в явном модуле, а дескриптор его модуля не объявляет, что он используетservice
loadInstalled
public static <S> ServiceLoader<S> loadInstalled(Class<S> service)
Этот метод-утилита эквивалентен:
ServiceLoader.load(service, ClassLoader.getPlatformClassLoader())
Этот метод предназначен для использования в случаях, когда требуются только установленные поставщики. Результирующий загрузчик сервисов будет находить и загружать только поставщиков, которые были установлены в текущей виртуальной машине Java; поставщики из пути модуля или пути класса приложения будут проигнорированы.
- Параметры типа:
-
S- класс типа сервиса - Параметры:
-
service- интерфейс или абстрактный класс, представляющий сервис - Возвращает:
- Новый загрузчик сервисов
- Выбрасывает:
-
ServiceConfigurationError- если тип сервиса недоступен для вызывающего или вызывающий находится в явном модуле, и его дескриптор модуля не объявляет, что он используетservice
load
public static <S> ServiceLoader<S> load(ModuleLayer layer, Class<S> service)
iterator и stream находят поставщиков и возвращают элементы, следующий: Поставщики находятся в слое модулей до поиска поставщиков в родительских слоях. Обход родительских слоев происходит по принципу глубины с посещением каждого слоя не более одного раза. Например, предположим, что L0 - это загрузчик начальных модулей, L1 и L2 - это слои модулей с L0 в качестве родителя. Теперь предположим, что L3 создан с L1 и L2 в качестве родителей (в указанном порядке). Использование загрузчика сервисов для поиска поставщиков с L3 в качестве контекста будет искать поставщиков в следующем порядке: L3, L1, L0, L2.
Если модуль объявляет более одного поставщика, то поставщики находятся в порядке, в котором его дескриптор модуля перечисляет поставщиков. Поставщики, добавленные динамически агентами инструментирования, всегда находятся после поставщиков, объявленных модулем.
Порядок модулей в слое модулей не определён.
- Примечание API:
- В отличие от других методов load, определённых здесь, тип сервиса является вторым параметром. Причина в том, чтобы избежать проблем с совместимостью исходного кода для кода, который использует
load(S, null). - Параметры типа:
-
S- класс типа сервиса - Параметры:
-
layer- слой модулей -
service- интерфейс или абстрактный класс, представляющий сервис - Возвращает:
- Новый загрузчик сервисов
- Выбрасывает:
-
ServiceConfigurationError- если тип сервиса недоступен для вызывающего или вызывающий находится в явном модуле, и его дескриптор модуля не объявляет, что он используетservice - С:
- 9
findFirst
public Optional<S> findFirst()
iterator() и получению первого элемента. Поэтому он возвращает первый элемент из кэша поставщиков, если возможно; в противном случае пытается загрузить и инициализировать первого поставщика. Следующий пример загружает первого доступного поставщика сервиса. Если поставщики сервисов не найдены, используется реализация по умолчанию.
CodecFactory factory = ServiceLoader.load(CodecFactory.class)
.findFirst()
.orElse(DEFAULT_CODECSET_FACTORY);
- Возвращает:
- Первый поставщик сервиса или пустой
Optional, если поставщики сервисов не найдены - Выбрасывает:
-
ServiceConfigurationError- Если класс поставщика не может быть загружен по любой из причин, указанных в разделе Ошибки выше. - С:
- 9
reload
public void reload()
После вызова этого метода последующие вызовы методов iterator или stream будут лениво искать поставщиков (и инициализировать в случае iterator) заново, как и для недавно созданного загрузчика сервисов.
Этот метод предназначен для ситуаций, в которых новые поставщики сервисов могут быть установлены в работающую виртуальную машину Java.
toString
public String toString()
- Переопределяет:
-
toStringв классеObject - Возвращает:
- Описание сервиса в виде строки
© 1993, 2023, Oracle and/or its affiliates. All rights reserved.
Documentation extracted from Debian's OpenJDK Development Kit package.
Licensed under the GNU General Public License, version 2, with the Classpath Exception.
Various third party code in OpenJDK is licensed under different licenses (see Debian package).
Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/ServiceLoader.html