Spec-Zone.ru › OpenJDK 24

Класс ServiceLoader<S>

java.lang.Object
java.util.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());
 
  1. Поток объектов Provider<CodecFactory>
  2. p.type() возвращает Class<CodecFactory>
  3. get() возвращает экземпляр CodecFactory

Разработка сервисов

Сервис — это один тип, обычно интерфейс или абстрактный класс. Можно использовать конкретный класс, но это не рекомендуется. Тип может иметь любой уровень доступа. Методы сервиса сильно зависят от предметной области, поэтому это описание API не может дать конкретных рекомендаций по их форме или функции. Однако есть два общих руководства:

  1. Сервис должен объявлять столько методов, сколько необходимо, чтобы позволить поставщикам сервиса сообщать о своих свойствах предметной области и других факторах качества реализации. Приложение, которое получает загрузчик сервиса для сервиса, может затем вызывать эти методы на каждом экземпляре поставщика сервиса, чтобы выбрать лучшего поставщика для приложения.

  2. Сервис должен выражать, предназначены ли его поставщики сервиса для прямой реализации сервиса или для механизма косвенного доступа, такого как "прокси" или "фабрика". Поставщики сервиса часто являются механизмами косвенного доступа, когда объекты предметной области относительно дорого инициализируются; в этом случае сервис должен быть разработан таким образом, чтобы поставщики сервиса были абстракциями, которые создают "реальное" воплощение по требованию. Например, сервис 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

Краткое описание вложенных классов

Modifier and Type Class Description
static interface  ServiceLoader.Provider<S>
Представляет поставщика сервиса, найденного с помощью ServiceLoader.

Краткое описание методов

Modifier and Type Method Description
Optional<S> findFirst()
Загружает первый доступный поставщик сервиса этого загрузчика.
Iterator<S> iterator()
Возвращает итератор для ленивой загрузки и создания доступных поставщиков сервиса этого загрузчика.
static <S> ServiceLoader<S> load(Class<S> service)
Создаёт новый загрузчик сервисов для заданного типа сервиса, используя контекстный загрузчик класса текущего потока.
static <S> ServiceLoader<S> load(Class<S> service, ClassLoader loader)
Создаёт новый загрузчик сервисов для заданного сервиса.
static <S> ServiceLoader<S> load(ModuleLayer layer, Class<S> service)
Создаёт новый загрузчик сервисов для заданного типа сервиса для загрузки поставщиков сервисов из модулей в заданном слое модулей и его предков.
static <S> ServiceLoader<S> loadInstalled(Class<S> service)
Создаёт новый загрузчик сервисов для заданного типа сервиса, используя платформенный загрузчик классов.
void reload()
Очищает кэш поставщиков этого загрузчика, чтобы все поставщики были перезагружены.
Stream<ServiceLoader.Provider<S>> 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, для получения или создания поставщика необходимо вызвать метод Provider's 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: Поиск поставщиков в именованных модулях.

    Поставщики сервиса находятся во всех именованных модулях загрузчика классов или в любом загрузчике классов, доступном через делегирование родителя.

    Кроме того, если загрузчик классов не является загрузчиком базовых классов или платформенным загрузчиком классов, то поставщики сервиса могут находиться в именованных модулях других загрузчиков классов. В частности, если у загрузчика классов или любого загрузчика классов, доступного через делегирование родителя, есть модуль в слое модуля, то ищутся поставщики сервиса во всех модулях в слое модуля.

    Например, предположим, что есть слой модуля, где каждый модуль находится в своём загрузчике классов (см. defineModulesWithManyLoaders). Если этот метод ServiceLoader.load вызывается для поиска поставщиков с использованием любого из загрузчиков классов, созданных для слоя модуля, то он найдёт всех поставщиков в слое модуля независимо от их определяющего загрузчика классов.

    Порядок: Загрузчик сервиса сначала найдёт любых поставщиков сервиса в модулях, определённых для загрузчика классов, затем его родительского загрузчика классов, его родительского родительского и так далее до загрузчика базовых классов. Если у загрузчика классов есть модули в слое модуля, то все поставщики в этом слое модуля находятся (независимо от их загрузчика классов) до поиска поставщиков в родительском загрузчике классов. Порядок модулей в одном загрузчике классов или порядок модулей в слое модуля не определён.

    Если модуль объявляет более одного поставщика, то поставщики находятся в том порядке, в котором модуль описания перечисляет поставщиков. Поставщики, добавленные динамически агентами инструментирования (см. redefineModule) всегда находятся после поставщиков, объявленных модулем.

  • Шаг 2: Поиск поставщиков в безымянных модулях.

    Поставщики сервиса в безымянных модулях находятся, если их имена классов указаны в файлах конфигурации поставщиков, найденных методом getResources загрузчика классов.

    Порядок основан на порядке, в котором метод getResources загрузчика классов находит файлы конфигурации сервиса, и в пределах этого - на порядке, в котором имена классов перечислены в файле.

    В файле конфигурации поставщика любая ссылка на поставщика сервиса, развернутого в именованном модуле, игнорируется. Это делается для предотвращения дублирования, которое могло бы возникнуть, если бы именованный модуль содержал как директиву provides, так и файл конфигурации поставщиков, упоминающий того же поставщика сервиса.

    Класс поставщика должен быть виден загрузчику классов.

Примечание API:
Если путь к классу загрузчика классов включает удалённые URL-адреса сети, то эти URL-адреса могут быть обработаны в процессе поиска файлов конфигурации поставщиков.

Эта активность является нормальной, хотя она может создавать непонятные записи в логах веб-сервера. Однако, если веб-сервер не настроен правильно, это может привести к ошибочной работе алгоритма загрузки поставщиков.

Веб-сервер должен возвращать ответ HTTP 404 (Not Found), когда запрошенного ресурса не существует. Иногда, однако, веб-серверы ошибочно настроены на возврат ответа HTTP 200 (OK) вместе со страницей ошибки HTML в таких случаях. Это приведёт к сгенерированию исключения ServiceConfigurationError при попытке этого класса разобрать страницу HTML как файл конфигурации поставщика. Лучшее решение этой проблемы заключается в исправлении неправильно настроенного веб-сервера на возврат правильного кода ответа (HTTP 404) вместе со страницей ошибки HTML.

Параметры типа:
S - класс типа сервиса
Параметры:
service - Интерфейс или абстрактный класс, представляющий сервис
loader - Загрузчик классов, который будет использоваться для загрузки файлов конфигурации поставщиков и классов поставщиков, или null, если необходимо использовать системный загрузчик классов (или, если это невозможно, загрузчик базовых классов)
Возвращает:
Новый загрузчик сервиса
Выбрасывает:
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(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, 2025, 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://download.java.net/java/early_access/jdk24/docs/api/java.base/java/util/ServiceLoader.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API