Яка різниця між інтерфейсом постачальника послуг (SPI) та інтерфейсом програмування прикладних програм (API) ?
Більш конкретно, для бібліотек Java, що робить їх API та / або SPI?
Яка різниця між інтерфейсом постачальника послуг (SPI) та інтерфейсом програмування прикладних програм (API) ?
Більш конкретно, для бібліотек Java, що робить їх API та / або SPI?
Відповіді:
Інакше кажучи, API повідомляє вам, що конкретний клас / метод робить для вас, а SPI повідомляє, що вам потрібно зробити, щоб відповідати.
Зазвичай API та SPI є окремими. Наприклад, в JDBC клас є частиною SPI: Якщо ви просто хочете використовувати JDBC, вам не потрібно використовувати його безпосередньо, але кожен , хто реалізує драйвер JDBC повинен реалізовувати цей клас.Driver
Однак іноді вони перетинаються. Інтерфейс є як SPI і API: Ви можете використовувати його регулярно , коли ви використовуєте драйвер JDBC , і він повинен бути реалізований розробником драйвера JDBC.Connection
@SomeAnnotation
до свого класу, щоб отримати його за допомогою якоїсь основи, чи вважатиметься цей клас анотацій SomeAnnotation.class
частиною SPI, хоча я технічно не поширюю чи впроваджую його?
Від ефективної Java, 2-е видання :
Рамка постачальника послуг - це система, в якій кілька постачальників послуг реалізують послугу, і система робить реалізацію доступною для своїх клієнтів, відриваючи їх від реалізації.
Є три основні компоненти структури постачальника послуг: сервісний інтерфейс, який постачальники реалізують; API реєстрації провайдера, який система використовує для реєстрації реалізацій, надаючи клієнтам доступ до них; і API доступу до сервісу, який клієнти використовують для отримання примірника послуги. API доступу до сервісу зазвичай дозволяє, але не вимагає від клієнта вказувати деякі критерії для вибору постачальника. За відсутності такої специфікації API повертає екземпляр реалізації за замовчуванням. API доступу до сервісу - це «гнучка статична фабрика», яка є основою системи постачальника послуг.
Необов'язковий четвертий компонент основи постачальника послуг - це інтерфейс постачальника послуг, який постачальники реалізують для створення примірників своєї служби. За відсутності інтерфейсу постачальника послуг реалізації реєструються за назвою класу та інстанціюються рефлекторно (Пункт 53). У випадку JDBC Connection відіграє частину інтерфейсу сервісу, DriverManager.registerDriver - API реєстрації постачальника, DriverManager.getConnection - API доступу до сервісу, а Driver - інтерфейс постачальника послуг.
Існує чимало варіантів структури структури постачальника послуг. Наприклад, API доступу до сервісу може повернути багатший сервісний інтерфейс, ніж той, що вимагається від постачальника, використовуючи шаблон адаптера [Gamma95, с. 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.
API розшифровується як інтерфейс програмування прикладних програм, де API - це засіб доступу до послуги / функції, що надається певним програмним забезпеченням або платформою.
SPI означає інтерфейс постачальника послуг, де SPI - це спосіб введення, розширення або зміна поведінки програмного забезпечення або платформи.
API зазвичай є цільовим для клієнтів, які мають доступ до послуги, і має такі властивості:
-> API - це програмний спосіб доступу до послуги для досягнення певної поведінки чи результатів
-> З точки зору еволюції API, додавання зовсім не є проблемою для клієнтів
-> Але один раз API, який використовується клієнтами, не може (і не повинен) змінюватися / видалятися, якщо немає відповідних комунікацій, оскільки його повна деградація очікування клієнта
SPI з іншого боку орієнтований на провайдерів і має такі властивості:
-> SPI - це спосіб розширити / змінити поведінку програмного забезпечення або платформи (програмований проти програматичного)
-> Еволюція SPI відрізняється від еволюції API, у видаленні SPI це не проблема
-> Додавання інтерфейсів SPI спричинить проблеми та може порушити існуючі реалізації
Для отримання додаткових пояснень натисніть тут: Інтерфейс постачальника послуг
FAQ щодо 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), не потребує байдуж, чи є система управління версіями чи що це таке.
Є один аспект, який, здається, не особливо висвітлений, але дуже важливий для розуміння міркувань щодо існування розколу 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 та фреймворки не піддаються впливу, abstract class
оскільки вони блокують їхню подальшу еволюцію щодо відсталої сумісності.
Якщо щось все ще незрозуміло, рекомендую переглянути цю сторінку, яка пояснює вище, більш детально.
(*) Зауважте, це справедливо лише до того, поки Java 1.8 не введе концепцію default
методів, визначених в інтерфейсі.
Я думаю, що слоти SPI у більшій системі, реалізуючи певні функції API, а потім зареєструвати себе як доступні через механізми пошуку служб. API використовується кодом програми кінцевого користувача безпосередньо, але може інтегрувати компоненти SPI. Це різниця між інкапсуляцією та прямим використанням.
Інтерфейс постачальника послуг - це сервісний інтерфейс, який повинні впроваджувати всі провайдери. Якщо жодна з існуючих провайдерів не працює для вас, вам потрібно написати власного постачальника послуг (реалізуючи інтерфейс сервісу) та десь зареєструватися (див. Корисну публікацію Романа).
Якщо ви повторно використовуєте реалізацію сервісного інтерфейсу існуючого постачальника, ви в основному використовуєте API цього конкретного провайдера, який включає всі методи сервісного інтерфейсу плюс кілька власних публічних методів. Якщо ви використовуєте методи API провайдера поза SPI, ви використовуєте особливості постачальника.
У світі Java різні технології мають бути модульними та "підключитися" до сервера додатків. Потім є різниця між
Два приклади таких технологій: JTA (менеджер транзакцій) та JCA (адаптер для JMS або бази даних). Але є й інші.
Потім реалізатор такої підключуваної технології повинен реалізувати SPI для підключення в додатку. сервер та надають API, який буде використовуватися додатком кінцевого користувача. Прикладом JCA є інтерфейс ManagedConnection, який є частиною SPI, та З'єднання, що є частиною API кінцевого користувача.