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

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

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

9 ответов


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

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

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

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


С эффективная Java, 2-е издание:

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

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

необязательный четвертый компонент a рамки поставщик услуг интерфейс поставщика услуг, который поставщики реализуют для создания примеры их службы реализация. При отсутствии интерфейс поставщика услуг , реализации регистрируются имя класса и экземпляр рефлективно (пункт 53). В случае JDBC, соединение играет роль сервисный интерфейс, DriverManager.registerDriver является Регистрация провайдера ПРИКЛАДНОЙ ПРОГРАММНЫЙ ИНТЕРФЕЙС, DriverManager.метод getconnection является API доступа к службе и драйвер интерфейс поставщика услуг.

существует множество вариантов шаблон структуры поставщика услуг. Например, 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();
    }
}

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

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

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

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

Enter image description here


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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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


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


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

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


в мире Java, различные технологии должны быть модульными и "сменной" на сервере приложений. Тогда есть разница между

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

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

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


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

API/SPI split требуется только тогда, когда ожидается развитие платформы. если вы пишете 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 и фреймворки не разоблачить abstract class поскольку они будут блокировать свою будущую эволюцию в отношении обратной совместимости.

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


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