Spec-Zone.ru › OpenJDK 27

Класс 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 возвращает Iterator, который сначала выдает все элементы, кэшированные во время предыдущих итераций, в порядке создания экземпляров, а затем лениво находит и создает экземпляры остальных поставщиков, поочередно добавляя каждый из них в кэш. Аналогично, каждый вызов метода stream возвращает Stream, который сначала обрабатывает всех поставщиков, загруженных при предыдущих операциях с потоками, в порядке загрузки, а затем лениво находит остальных поставщиков. Кэши очищаются с помощью метода reload.

Ошибки

При использовании iterator загрузчика служб методы hasNext и next завершаются с ошибкой ServiceConfigurationError, если при поиске, загрузке или создании экземпляра поставщика службы возникает ошибка. При обработке потока загрузчика служб ServiceConfigurationError может быть вызван любым методом, инициирующим поиск или загрузку поставщика службы.

При загрузке или создании экземпляра поставщика службы в модуле ServiceConfigurationError может быть вызван по следующим причинам:

  • Поставщик службы не удается загрузить.
  • Поставщик службы не объявляет метод-поставщик и либо несовместим с интерфейсом или классом службы, либо не имеет конструктора поставщика.
  • Поставщик службы объявляет общедоступный статический метод без аргументов с именем "provider", тип возвращаемого значения которого несовместим с интерфейсом или классом службы.
  • Файл класса поставщика службы содержит более одного общедоступного статического метода без аргументов с именем "provider".
  • Метод-поставщик, объявленный поставщиком службы, завершается с ошибкой, возвращая null или выбрасывая исключение.
  • Поставщик службы не объявляет метод-поставщик, а его конструктор поставщика завершается с ошибкой, выбрасывая исключение.

При чтении файла конфигурации поставщика или загрузке либо создании экземпляра класса поставщика, указанного в таком файле, ServiceConfigurationError может быть вызван по следующим причинам:

  • Формат файла конфигурации поставщика нарушает указанный выше формат;
  • При чтении файла конфигурации поставщика возникает IOException;
  • Поставщика службы не удается загрузить;
  • Поставщик службы несовместим с интерфейсом или классом службы, не определяет конструктор поставщика или не может быть создан.

Параллельное выполнение

Экземпляры этого класса небезопасно использовать из нескольких потоков одновременно.

Обработка null

Если не указано иное, передача аргумента null любому методу этого класса приводит к выбрасыванию исключения NullPointerException.

Начиная с версии:
1.6

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

Модификатор и тип Класс Описание
static interface  ServiceLoader.Provider<S>
Представляет поставщика службы, найденного с помощью ServiceLoader.

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

Модификатор и тип Метод Описание
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()
Возвращает строку с описанием этой службы.

Методы, объявленные в классе Object

clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
Модификатор и тип Метод Описание
protected Object clone()
Создает и возвращает копию этого объекта.
boolean equals(Object obj)
Указывает, равен ли этот объект другому объекту.
protected void finalize()
Устарело, будет удалено: этот элемент API подлежит удалению в будущей версии.
Финализация объявлена устаревшей и подлежит удалению в одном из будущих выпусков.
final Class<?> getClass()
Возвращает класс времени выполнения этого Object.
int hashCode()
Возвращает хеш-код этого объекта.
final void notify()
Пробуждает один поток, ожидающий на мониторе этого объекта.
final void notifyAll()
Пробуждает все потоки, ожидающие на мониторе этого объекта.
final void wait()
Заставляет текущий поток ждать, пока он не будет пробужден, обычно посредством уведомления или прерывания.
final void wait(long timeoutMillis)
Заставляет текущий поток ждать, пока он не будет пробужден, обычно посредством уведомления или прерывания либо пока не истечет заданное время.
final void wait(long timeoutMillis, int nanos)
Заставляет текущий поток ждать, пока он не будет пробужден, обычно посредством уведомления или прерывания либо пока не истечет заданное время.

Методы, объявленные в интерфейсе Iterable

forEach, spliterator
Модификатор и тип Метод Описание
default void forEach(Consumer<? super S> action)
Выполняет заданное действие для каждого элемента Iterable, пока не будут обработаны все элементы или действие не вызовет исключение.
default Spliterator<S> spliterator()
Создает Spliterator для элементов, описанных этим Iterable.

Подробное описание методов

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 объекта Provider.

Для обеспечения ленивой загрузки фактический поиск поставщиков выполняется при обработке потока. Если поставщик службы невозможно загрузить по любой из причин, указанных выше в разделе Ошибки, то метод, вызвавший загрузку поставщика службы, выбрасывает ServiceConfigurationError.

Кэширование: при обработке потока сначала обрабатываются поставщики, ранее загруженные операциями с потоками, в порядке загрузки. Затем лениво загружаются все оставшиеся поставщики службы. Если кэши поставщиков этого загрузчика очищены вызовом метода reload, существующие потоки этого загрузчика служб следует отбросить. Исходный spliterator возвращаемого потока работает в режиме fail-fast и выбросит 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 (Не найдено). Однако иногда веб-серверы ошибочно настроены так, что в таких случаях возвращают ответ HTTP 200 (ОК) вместе с полезной HTML-страницей ошибки. Когда этот класс попытается разобрать HTML-страницу как файл конфигурации поставщика, это приведет к выбрасыванию ServiceConfigurationError. Лучшее решение этой проблемы — исправить настройки веб-сервера, чтобы он возвращал правильный код ответа (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, тип службы является вторым параметром. Это сделано, чтобы избежать проблем с совместимостью исходного кода для кода, использующего 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
Возвращает:
Строка с описанием

Сообщить об ошибке или предложить улучшение
Дополнительные справочные материалы по API и документацию для разработчиков см. в разделе Документация Java SE, содержащем более подробные описания для разработчиков, концептуальные обзоры, определения терминов, обходные решения и рабочие примеры кода. Другие версии.
Java является товарным знаком или зарегистрированным товарным знаком Oracle и/или ее аффилированных лиц в США и других странах.
Авторские права © 1993, 2026, Oracle и/или ее аффилированные лица, 500 Oracle Parkway, Redwood Shores, CA 94065 USA.
Все права защищены. Использование регулируется условиями лицензии и политикой распространения документации.

© 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.

Spec-Zone.ru

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