Spec-Zone.ru › OpenJDK 8

Класс ServiceLoader<S>

  • java.lang.Object
    • java.util.ServiceLoader<S>
Параметры типа:
S - Тип службы, которая должна быть загружена этим загрузчиком
Все реализованные интерфейсы:
Iterable<S>

public final class ServiceLoader<S>
extends Object
implements Iterable<S>

Простая утилита для загрузки поставщиков сервисов.

Служба — это хорошо известный набор интерфейсов и (обычно абстрактных) классов. Поставщик службы — это конкретная реализация службы. Классы в поставщике обычно реализуют интерфейсы и наследуются от классов, определённых в самой службе. Поставщики служб могут быть установлены в реализации Java-платформы в виде расширений, то есть файлов jar, помещённых в любые стандартные каталоги расширений. Поставщики также могут быть доступны путём добавления их в пути класса приложения или другими средствами, специфичными для платформы.

Для целей загрузки служба представляется одним типом, то есть одним интерфейсом или абстрактным классом. (Можно использовать конкретный класс, но это не рекомендуется.) Поставщик данной службы содержит один или несколько конкретных классов, которые расширяют этот тип службы с данными и кодом, специфичными для поставщика. Класс поставщика обычно не является полным поставщиком, а скорее прокси, который содержит достаточную информацию для определения, может ли поставщик удовлетворить конкретный запрос, а также код, который может создать фактического поставщика по запросу. Подробности классов поставщиков обычно сильно зависят от конкретной службы; ни один отдельный класс или интерфейс не мог бы их объединить, поэтому такой тип здесь не определён. Единственное требование, налагаемое этой утилитой, заключается в том, что классы поставщиков должны иметь конструктор без аргументов, чтобы их можно было создать во время загрузки.

Поставщик службы идентифицируется путём размещения файла конфигурации поставщика в каталоге ресурсов META-INF/services. Имя файла — это полное бинарное имя типа службы. Файл содержит список полных бинарных имён конкретных классов поставщиков, по одному на строке. Пробелы и символы табуляции вокруг каждого имени, а также пустые строки игнорируются. Символом комментария является '#' ('\u0023', ДИЕЗ); в каждой строке все символы после первого символа комментария игнорируются. Файл должен быть закодирован в формате UTF-8.

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

Поставщики обнаруживаются и создаются лениво, то есть по требованию. Загрузчик служб сохраняет кэш поставщиков, которые были загружены до сих пор. Каждый вызов метода iterator возвращает итератор, который сначала возвращает все элементы кэша в порядке создания, а затем лениво находит и создаёт любые оставшиеся поставщики, добавляя каждый из них в кэш по очереди. Кэш можно очистить с помощью метода reload.

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

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

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

Пример Предположим, у нас есть тип службы com.example.CodecSet, который предназначен для представления наборов пар кодировщик/декодировщик для некоторого протокола. В этом случае это абстрактный класс с двумя абстрактными методами:

public abstract Encoder getEncoder(String encodingName);
public abstract Decoder getDecoder(String encodingName);
Каждый метод возвращает соответствующий объект или null если поставщик не поддерживает заданное кодирование. Типичные поставщики поддерживают более одного кодирования.

Если com.example.impl.StandardCodecs является реализацией службы CodecSet, то её файл jar также содержит файл с именем

META-INF/services/com.example.CodecSet

Этот файл содержит единственную строку:

com.example.impl.StandardCodecs    # Standard codecs

Класс CodecSet создаёт и сохраняет единственный экземпляр службы при инициализации:

private static ServiceLoader<CodecSet> codecSetLoader
    = ServiceLoader.load(CodecSet.class);

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

public static Encoder getEncoder(String encodingName) {
    for (CodecSet cp : codecSetLoader) {
        Encoder enc = cp.getEncoder(encodingName);
        if (enc != null)
            return enc;
    }
    return null;
}

Аналогичным образом определяется метод getDecoder.

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

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

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

C момента:
1.6

Методы

Модификатор и тип Метод и описание
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> loadInstalled(Class<S> service)

Создаёт новый загрузчик служб для данного типа службы, используя загрузчик классов расширений.

void reload()

Очищает кэш поставщиков этого загрузчика, чтобы все поставщики были перезагружены.

String toString()

Возвращает строку, описывающую эту службу.

Методы, унаследованные от класса java.lang.Object

clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait

Методы, унаследованные от интерфейса java.lang.Iterable

forEach, spliterator

Методы

reload

public void reload()

Очищает кэш поставщиков этого загрузчика, чтобы все поставщики были перезагружены.

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

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

iterator

public Iterator<S> iterator()

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

Итератор, возвращаемый этим методом, сначала возвращает все элементы кэша поставщиков в порядке инициализации. Затем он лениво загружает и инициализирует любые оставшиеся поставщики, добавляя каждый из них в кэш по очереди.

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

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

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

Итератор, возвращаемый этим методом, не поддерживает удаление. Вызов его метода remove приведет к выбросу исключения UnsupportedOperationException.

Указано в:
iterator в интерфейсе Iterable<S>
Примечание по реализации:
При добавлении поставщиков в кэш, Iterator обрабатывает ресурсы в том порядке, в котором метод ClassLoader.getResources(String) находит файлы конфигурации службы.
Возвращает:
Итератор, который лениво загружает поставщиков для службы этого загрузчика

load

public static <S> ServiceLoader<S> load(Class<S> service,
                                        ClassLoader loader)

Создает новый загрузчик службы для заданного типа службы и загрузчика классов.

Тип параметров:
S - класс типа службы
Параметры:
service - Интерфейс или абстрактный класс, представляющий службу
loader - Загрузчик классов, который будет использоваться для загрузки файлов конфигурации поставщиков и классов поставщиков, или null , если необходимо использовать системный загрузчик классов (или, при его отсутствии, загрузчик базового класса)
Возвращает:
Новый загрузчик службы

load

public static <S> ServiceLoader<S> load(Class<S> service)

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

Вызов этого вспомогательного метода в форме

ServiceLoader.load(service)
эквивалентен
ServiceLoader.load(service,
                   Thread.currentThread().getContextClassLoader())
Тип параметров:
S - класс типа службы
Параметры:
service - Интерфейс или абстрактный класс, представляющий службу
Возвращает:
Новый загрузчик службы

loadInstalled

public static <S> ServiceLoader<S> loadInstalled(Class<S> service)

Создает новый загрузчик службы для заданного типа службы, используя расширяемый загрузчик классов.

Этот вспомогательный метод просто находит расширяемый загрузчик классов, назовем его extClassLoader, и затем возвращает

ServiceLoader.load(service, extClassLoader)

Если расширяемый загрузчик классов не может быть найден, используется системный загрузчик классов; если системного загрузчика классов нет, используется загрузчик базового класса.

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

Тип параметров:
S - класс типа службы
Параметры:
service - Интерфейс или абстрактный класс, представляющий службу
Возвращает:
Новый загрузчик службы

toString

public String toString()

Возвращает строку, описывающую эту службу.

Переопределяет:
toString в классе Object
Возвращает:
Описание в виде строки

© 1993, 2020, 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