Разница между SPI и API?

Ответы:

395
  • API - это описание классов / интерфейсов / методов / ..., которые вы вызываете и используете для достижения цели, и
  • SPI - это описание классов / интерфейсов / методов / ..., которые вы расширяете и внедряете для достижения цели.

Иными словами, API сообщает вам, что для вас делает определенный класс / метод, а SPI говорит вам, что вы должны сделать, чтобы соответствовать.

Обычно API и SPI являются отдельными. Например, в JDBC класс является частью SPI: Если вы просто хотите использовать JDBC, вам не нужно использовать его непосредственно, но каждый , кто реализует драйвер JDBC должен реализовывать этот класс.Driver

Однако иногда они перекрываются. Интерфейс является как SPI и API: Вы можете использовать его регулярно , когда вы используете драйвер JDBC , и он должен быть реализован разработчиком драйвера JDBC.Connection

Йоахим Зауэр
источник
звучит о праве. просто линии между SPI и API могут быть немного серыми, так как большинство API имеет абстрактные классы / интерфейсы, которые пользователь может реализовать для достижения цели ...
kctang
1
@koss: большинство API? Я знаю, что вы имеете в виду, но я не вижу этих вещей много.
Иоахим Зауэр
2
API больше подходит разработчикам, а SPI - поставщикам.
Азфар Ниаз
7
@AzfarNiaz: ну, поскольку поставщики нанимают разработчиков для создания своих продуктов, оба имеют отношение к разработчикам ;-)
Joachim Sauer
В Java аннотации являются частью SPI? Например, если мне нужно добавить @SomeAnnotationв свой класс, чтобы его подобрал какой-то фреймворк, будет ли этот класс аннотаций SomeAnnotation.classсчитаться частью SPI, даже если я технически не расширяю или не реализую его?
Адам Берли
59

Из эффективной Java, 2-е издание :

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

Существуют три основных компонента структуры поставщика услуг: интерфейс службы, который реализуют поставщики; API регистрации провайдера, который система использует для регистрации реализаций, предоставляя клиентам доступ к ним; и API доступа к сервису, который клиенты используют для получения экземпляра сервиса. API доступа к сервису обычно позволяет, но не требует от клиента указывать некоторые критерии для выбора поставщика. В отсутствие такой спецификации API возвращает экземпляр реализации по умолчанию. API доступа к сервису - это «гибкая статическая фабрика», которая составляет основу инфраструктуры поставщика услуг.

Необязательным четвертым компонентом структуры поставщика услуг является интерфейс поставщика услуг, который поставщики реализуют для создания экземпляров реализации своих услуг. В отсутствие интерфейса поставщика услуг реализации регистрируются по имени класса и создаются рефлексивно (Элемент 53). В случае JDBC Connection играет роль интерфейса службы, DriverManager.registerDriver - это API регистрации поставщика, DriverManager.getConnection - это API доступа к службе, а Driver - интерфейс поставщика службы.

Существует множество вариантов шаблона структуры поставщика услуг. Например, API доступа к сервису может вернуть более богатый интерфейс сервиса, чем тот, который требуется от провайдера, используя шаблон адаптера [Gamma95, p. 139]. Вот простая реализация с интерфейсом поставщика услуг и поставщиком по умолчанию:

// Service provider framework sketch

// Service interface
public interface Service {
    ... // Service-specific methods go here
}

// Service provider interface
public interface Provider {
    Service newService();
}

// Noninstantiable class for service registration and access
public class Services {
    private Services() { }  // Prevents instantiation (Item 4)

    // Maps service names to services
    private static final Map<String, Provider> providers =
        new ConcurrentHashMap<String, Provider>();
    public static final String DEFAULT_PROVIDER_NAME = "<def>";

    // Provider registration API
    public static void registerDefaultProvider(Provider p) {
        registerProvider(DEFAULT_PROVIDER_NAME, p);
    }
    public static void registerProvider(String name, Provider p){
        providers.put(name, p);
    }

    // Service access API
    public static Service newInstance() {
        return newInstance(DEFAULT_PROVIDER_NAME);
    }
    public static Service newInstance(String name) {
        Provider p = providers.get(name);
        if (p == null)
            throw new IllegalArgumentException(
                "No provider registered with name: " + name);
        return p.newService();
    }
}
Римский
источник
3
спасибо за очень хорошее описание в рамках провайдера услуг. это будет полезно знать. однако, это не ясно описывает «разницу» между API и SPI, поэтому я не буду ставить здесь галочку ... ;-)
kctang
23

Разница между API и SPI возникает, когда API дополнительно предоставляет некоторые конкретные реализации. В этом случае поставщик услуг должен реализовать несколько API (называемых SPI).

Примером является JNDI:

JNDI предоставляет интерфейсы и некоторые классы для поиска по контексту. Способ поиска контекста по умолчанию предоставляется в IntialContext. Этот класс внутренне будет использовать интерфейсы SPI (используя NamingManager) для конкретных реализаций провайдера.

Посмотрите Архитектуру JNDI ниже для лучшего понимания.

Введите описание изображения здесь

Сандип Джиндал
источник
22

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

SPI расшифровывается как Service Provider Interface, где SPI - это способ внедрить, расширить или изменить поведение программного обеспечения или платформы.

API обычно предназначен для доступа клиентов к сервису и имеет следующие свойства:

-> API - это программный способ доступа к сервису для достижения определенного поведения или вывода

-> С точки зрения развития API, добавление не является проблемой для клиентов

-> Но API, когда-то использованный клиентами, не может (и не должен) изменяться / удаляться, если нет соответствующей связи, так как это полностью ухудшает ожидания клиента

SPI, с другой стороны, предназначен для поставщиков и имеет следующие свойства:

-> SPI - это способ расширить / изменить поведение программного обеспечения или платформы (программируемый или программный)

-> Развитие SPI отличается от развития API, удаление SPI не является проблемой

-> Добавление интерфейсов SPI вызовет проблемы и может нарушить существующие реализации

Для получения более подробной информации нажмите здесь: Интерфейс поставщика услуг

Венката Адитья Паван
источник
12

Часто задаваемые вопросы по NetBeans: что такое SPI? Чем он отличается от API?

API - это общий термин - аббревиатура для интерфейса прикладного программирования - он означает что-то (в Java, обычно в некоторых классах Java) часть программного обеспечения, которое позволяет другим программам взаимодействовать с ним.

SPI означает интерфейс поставщика услуг. Это подмножество всех вещей, которые могут быть специфичными для API в ситуациях, когда библиотека предоставляет классы, которые вызываются приложением (или библиотекой API), и которые обычно изменяют возможности приложения.

Классическим примером является JavaMail. Его API имеет две стороны:

  • Сторона API - которую вы вызываете, если пишете почтовый клиент или хотите прочитать почтовый ящик
  • Сторона SPI, если вы предоставляете обработчик проводного протокола, позволяющий JavaMail взаимодействовать с сервером нового типа, таким как сервер новостей или IMAP

Пользователям API редко нужно видеть классы SPI или разговаривать с ними, и наоборот.

В NetBeans, когда вы видите термин SPI, обычно говорят о классах, которые модуль может внедрить во время выполнения, которые позволяют NetBeans делать новые вещи. Например, существует общий SPI для реализации систем контроля версий. Различные модули предоставляют реализации этого SPI для CVS, Subversion, Mercurial и других систем контроля версий. Однако коду, который имеет дело с файлами (сторона API), не нужно заботиться о том, существует ли система контроля версий или какая она есть.

Ондра Жижка
источник
5

Есть один аспект, который, кажется, не особо выделяется, но очень важен для понимания причин существования разделения API / SPI.

Разделение API / SPI требуется только тогда, когда ожидается развитие платформы. Если вы пишете API и «знаете», он никогда не потребует каких-либо улучшений в будущем, нет никаких реальных причин для разделения вашего кода на две части (кроме создания чистого объектного дизайна).

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

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

Давайте покажем это на одном из известных объектов Java Collectionи Collections.


API: Collections набор служебных статических методов. Часто классы, представляющие объект API, определяются так, finalкак это гарантирует (во время компиляции), что ни один клиент не может «реализовать» этот объект, и они могут зависеть от «вызова» его статических методов, например

Collections.emptySet();

Поскольку все клиенты «вызывают», но не «внедряют» , авторы JDK могут добавлять новые методы в Collectionsобъект в будущей версии JDK. Они могут быть уверены, что это не сломает ни одного клиента, даже если его использование исчисляется миллионами.


SPI: Collection это интерфейс, который подразумевает, что любой может реализовать свою собственную версию. Таким образом, авторы JDK не могут добавлять в него новые методы, так как это нарушит работу всех клиентов, написавших свою собственную Collectionреализацию (*).

Как правило, когда требуется добавить дополнительный метод, необходимо создать новый интерфейс, например, Collection2который расширяет прежний. Затем клиент SPI может решить, следует ли перейти на новую версию SPI и реализовать его дополнительный метод, или же придерживаться более старого.


Возможно, вы уже видели смысл. Если вы объедините обе части в один класс, ваш API заблокирован от любых дополнений. Это также причина, по которой хорошие Java API и Frameworks не раскрываются, abstract classпоскольку они блокируют их дальнейшее развитие в отношении обратной совместимости.

Если что-то все еще неясно, я рекомендую проверить эту страницу, которая объясняет выше более подробно.


(*) Обратите внимание, что это верно только до Java 1.8, который вводит понятие defaultметодов, определенных в интерфейсе.

Мартин Яничек
источник
4

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

Крис Деннетт
источник
спасибо за ответ Крис. какие-либо примеры существующих библиотек Java (т.е. сервлетов, JDBC и т. д.)? ... например, как это делает их API / SPI. может быть трудно визуализировать разницу только с помощью описания.
2010 года
1
API - это JDBC, SPI для JDBC - это интерфейс соединителя базы данных, который разработчики SPI могут использовать для создания новых соединителей базы данных, которые разработчик может выбрать для использования.
Крис Деннетт
4

Интерфейс поставщика услуг - это интерфейс службы, который должны быть реализованы всеми поставщиками. Если ни одна из существующих реализаций провайдера не работает для вас, вам нужно написать собственного провайдера услуг (реализующий интерфейс сервиса) и где-нибудь зарегистрироваться (см. Полезный пост Романа).

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

Тапасви
источник
2

В мире Java различные технологии должны быть модульными и «подключаемыми» к серверу приложений. Тогда есть разница между

  • сервер приложений
    • [SPI]
  • подключаемая технология
    • [API]
  • приложение конечного пользователя

Двумя примерами таких технологий являются JTA (менеджер транзакций) и JCA (адаптер для JMS или базы данных). Но есть и другие.

Разработчик такой подключаемой технологии должен затем реализовать SPI для подключения в приложении. сервер и предоставить API для использования приложением конечного пользователя. Примером из JCA является интерфейс ManagedConnection, который является частью SPI, и Connection, который является частью API конечного пользователя.

ewernli
источник