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

В чем разница между интерфейсом поставщика услуг (SPI) и интерфейсом прикладного программирования (API) ?

Более конкретно, для библиотек Java, что делает их API и / или SPI?

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

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

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

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

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

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

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

Необязательный четвертый компонент структуры поставщика услуг – это интерфейс поставщика услуг, который провайдеры реализуют для создания экземпляров реализации своих услуг. В отсутствие интерфейса поставщика услуг реализации регистрируются по имени classа и отражаются рефлексивно (пункт 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 providers = new ConcurrentHashMap(); public static final String DEFAULT_PROVIDER_NAME = ""; // 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(); } } 

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

Примером может служить JNDI:

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

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

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

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

SPI означает интерфейс поставщика услуг, где SPI – это способ внедрения, расширения или изменения поведения программного обеспечения или платформы.

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

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

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

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

SPI с другой стороны нацелены на поставщиков и обладают следующими свойствами:

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

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

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

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

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

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

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

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

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

Пользователям API редко приходится видеть или разговаривать с classами SPI и наоборот.

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

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

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

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

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

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

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

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

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

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

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

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

Позволяет показать его на одном из известных Java-объектов Collection and Collections .


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

 Collections.emptySet(); 

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


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

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


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

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


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

  • Использование опций Java 8 с Stream :: flatMap
  • Как создать asynchronous HTTP-запрос в JAVA?
  • Apache HttpClient 4.0.3 - как установить cookie с sessionID для запроса POST?
  • Целочисленный class-shell и оператор == - где указано поведение?
  • Развертывание моего приложения в корневом каталоге Tomcat
  • Как решить «не удалось лениво инициализировать сборку роли» Исключение Hibernate
  • Как запустить мое приложение в качестве суперпользователя из Eclipse?
  • В чем разница между и ?
  • Различные способы загрузки файла в качестве InputStream
  • Как преобразовать массив объектов в строковый массив в Java
  • Почему Java-поддержка не проходит по ссылке, например, C ++
  • Interesting Posts

    Объявление переменной внутри или вне цикла foreach: что быстрее / лучше?

    Как получить доступ к элементу столбца VectorUDT в Spark DataFrame?

    Конструкторы и наследование по умолчанию в Java

    iOS Как обнаружить iPhone X, iPhone 6 плюс, iPhone 6, iPhone 5, iPhone 4 от макроса?

    Как установить версию Python по умолчанию на 3.x на OS X?

    Пример использования shared_ptr?

    Профиль пользователя Django

    Что такое «= C2 = A0» в MIME-кодированном, цитируемом тексте?

    Как отключить автоматические резервные копии Windows?

    Где можно найти настройки таймаута по умолчанию для всех браузеров?

    Является ли GParted очень надежным? Разве это так хорошо, как Magic Partition?

    Глобальный захват клавиатуры в приложении C #

    Почему я вижу странные значения при печати неинициализированных переменных?

    Восстановление данных при сбое жесткого диска с использованием ddrescue

    Использование DiskLruCache в android 4.0 не предусматривает метод openCache

    Давайте будем гением компьютера.