Différence entre SPI et API?

Quelle est la différence entre l’ interface de fournisseur de service (SPI) et l’ interface de programmation d’application (API) ?

Plus précisément, pour les bibliothèques Java, quelles sont les caractéristiques de ces API et / ou SPI?

  • L’API est la description des classes / interfaces / méthodes / … que vous appelez et utilisez pour atteindre un objective, et
  • le SPI est la description des classes / interfaces / méthodes / … que vous étendez et implémentez pour atteindre un objective.

En d’autres termes, l’API vous indique ce que fait une classe / méthode spécifique pour vous, et le SPI vous indique ce que vous devez faire pour vous conformer.

Les API et les SPI sont généralement séparés. Par exemple, dans JDBC, la classe Driver fait partie du SPI: si vous souhaitez simplement utiliser JDBC, vous n’avez pas besoin de l’utiliser directement, mais tous ceux qui implémentent un pilote JDBC doivent implémenter cette classe.

Parfois, ils se chevauchent. L’interface de Connection est à la fois SPI et API: vous l’utilisez régulièrement lorsque vous utilisez un pilote JDBC et il doit être implémenté par le développeur du pilote JDBC.

De Java efficace, 2e édition :

Une infrastructure de fournisseur de services est un système dans lequel plusieurs fournisseurs de services implémentent un service, et le système met les implémentations à la disposition de ses clients, en les découplant des implémentations.

Il existe trois composants essentiels d’un cadre de fournisseur de services: une interface de service, que les fournisseurs implémentent; une API d’enregistrement de fournisseur, que le système utilise pour enregistrer les implémentations, en donnant access aux clients; et une API d’access aux services, que les clients utilisent pour obtenir une instance du service. L’API d’access au service autorise généralement, mais n’exige pas que le client spécifie certains critères pour choisir un fournisseur. En l’absence d’une telle spécification, l’API renvoie une instance d’une implémentation par défaut. L’API d’access au service est la «fabrique statique flexible» qui constitue la base de la structure du fournisseur de services.

Un quasortingème composant facultatif d’une infrastructure de fournisseur de services est une interface de fournisseur de services, que les fournisseurs implémentent pour créer des instances de leur implémentation de service. En l’absence d’une interface de fournisseur de services, les implémentations sont enregistrées par nom de classe et instanciées de manière réfléchie (élément 53). Dans le cas de JDBC, Connection joue le rôle d’interface de service, DriverManager.registerDriver est l’API d’enregistrement du fournisseur, DriverManager.getConnection est l’API d’access au service et Driver est l’interface du fournisseur de services.

Il existe de nombreuses variantes du modèle de structure du fournisseur de services. Par exemple, l’API d’access au service peut renvoyer une interface de service plus riche que celle requirejse par le fournisseur, en utilisant le modèle d’adaptateur [Gamma95, p. 139]. Voici une implémentation simple avec une interface de fournisseur de services et un fournisseur par défaut:

 // 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 Ssortingng DEFAULT_PROVIDER_NAME = ""; // Provider registration API public static void registerDefaultProvider(Provider p) { registerProvider(DEFAULT_PROVIDER_NAME, p); } public static void registerProvider(Ssortingng name, Provider p){ providers.put(name, p); } // Service access API public static Service newInstance() { return newInstance(DEFAULT_PROVIDER_NAME); } public static Service newInstance(Ssortingng name) { Provider p = providers.get(name); if (p == null) throw new IllegalArgumentException( "No provider registered with name: " + name); return p.newService(); } } 

La différence entre API et SPI survient lorsqu’une API fournit des implémentations concrètes. Dans ce cas, le fournisseur de services doit implémenter quelques API (appelées SPI).

Un exemple est JNDI:

JNDI fournit des interfaces et des classes pour la recherche de contexte. La manière par défaut de rechercher un contexte est fournie dans IntialContext. Cette classe utilisera en interne des interfaces SPI (utilisant NamingManager) pour les implémentations spécifiques au fournisseur.

Voir l’architecture JNDI ci-dessous pour une meilleure compréhension.

Entrez la description de l'image ici

API signifie Application Programming Interface, où l’API est un moyen d’accéder à un service / fonction fourni par un logiciel ou une plate-forme.

SPI signifie Service Provider Interface, où SPI permet d’injecter, d’étendre ou de modifier le comportement d’un logiciel ou d’une plate-forme.

L’API est normalement la cible des clients pour accéder à un service et présente les propriétés suivantes:

-> L’API est un moyen programmatique d’accéder à un service pour obtenir un certain comportement ou une sortie

-> Du sharepoint vue de l’évolution de l’API, l’ajout n’est pas un problème pour les clients

-> Mais les API autrefois utilisées par les clients ne peuvent pas (et ne doivent pas) être modifiées / supprimées à moins qu’il y ait des communications appropriées, car il s’agit d’une dégradation complète des attentes du client

SPI d’autre part sont ciblés pour les fournisseurs et ont les propriétés suivantes:

-> SPI est un moyen d’étendre / modifier le comportement d’un logiciel ou d’une plate-forme (programmable ou programmatique)

-> L’évolution de SPI est différente de l’évolution de l’API, la suppression de SPI n’est pas un problème

-> L’ajout d’interfaces SPI posera des problèmes et peut casser les implémentations existantes

Pour plus d’explications, cliquez ici: Interface du fournisseur de services

FAQ NetBeans: Qu’est-ce qu’un SPI? En quoi est-ce différent d’une API?

L’API est un terme général – un acronyme pour Application Programming Interface – qui signifie quelque chose (en Java, généralement certaines classes Java) exposé par un logiciel, qui permet à d’autres logiciels de communiquer avec lui.

SPI signifie Service Provider Interface. C’est un sous-ensemble de tout ce qui peut être une API spécifique à des situations où une bibliothèque fournit des classes appelées par l’application (ou la bibliothèque API), et qui modifient généralement ce que l’application est capable de faire.

L’exemple classique est JavaMail. Son API a deux faces:

  • Le côté API – que vous appelez si vous écrivez un client de messagerie ou que vous souhaitez lire une boîte aux lettres
  • Le côté SPI si vous fournissez un gestionnaire de protocole filaire pour permettre à JavaMail de communiquer avec un nouveau type de serveur, tel qu’un serveur de news ou un serveur IMAP

Les utilisateurs de l’API ont rarement besoin de voir ou de parler aux classes SPI, et inversement.

Dans NetBeans, lorsque vous voyez le terme SPI, il s’agit généralement des classes qu’un module peut injecter à l’exécution, ce qui permet à NetBeans de faire de nouvelles choses. Par exemple, il existe un SPI général pour implémenter des systèmes de contrôle de version. Différents modules fournissent des implémentations de ce SPI pour CVS, Subversion, Mercurial et autres systèmes de contrôle de révision. Toutefois, le code qui traite des fichiers (côté API) n’a pas besoin de savoir s’il existe un système de contrôle de version ou ce qu’il est.

Je suppose qu’un SPI s’installe dans un système plus grand en implémentant certaines fonctionnalités d’une API, puis en s’enregistrant comme étant disponible via des mécanismes de recherche de service. Une API est utilisée directement par le code d’application de l’utilisateur final, mais peut intégrer des composants SPI. C’est la différence entre l’encapsulation et l’utilisation directe.

L’interface du fournisseur de services est l’interface de service que tous les fournisseurs doivent implémenter. Si aucune implémentation de fournisseur existante ne fonctionne pour vous, vous devez écrire votre propre fournisseur de services (implémentant l’interface de service) et vous enregistrer quelque part (voir la publication utile de Roman).

Si vous réutilisez l’implémentation existante du fournisseur de l’interface de service, vous utilisez essentiellement l’API de ce fournisseur particulier, qui inclut toutes les méthodes d’interface de service et quelques méthodes publiques propres. Si vous utilisez des méthodes d’API fournisseur en dehors du SPI, vous utilisez des fonctionnalités spécifiques au fournisseur.

Dans le monde Java, différentes technologies doivent être modulaires et «connectables» à un serveur d’applications. Il y a alors une différence entre

  • le serveur d’application
    • [SPI]
  • la technologie enfichable
    • [API]
  • l’application utilisateur final

JTA (le gestionnaire de transactions) et JCA (adaptateur pour JMS ou firebase database) en sont deux exemples. Mais il y en a d’autres.

L’implémenteur d’une telle technologie doit alors implémenter le SPI pour qu’il soit enfichable dans l’application. serveur et fournir une API à utiliser par l’application utilisateur final. Un exemple de JCA est l’interface ManagedConnection qui fait partie du SPI et la connexion qui fait partie de l’API de l’utilisateur final.

Il y a un aspect qui ne semble pas être beaucoup mis en évidence mais qui est très important pour comprendre le raisonnement derrière l’existence de la séparation API / SPI.

La séparation API / SPI n’est requirejse que lorsque la plate-forme doit évoluer. Si vous écrivez une API et que vous “savez” qu’elle ne nécessitera aucune amélioration future, il n’y a pas de raison réelle de diviser votre code en deux parties (en plus de la conception d’object propre).

Mais ce n’est presque jamais le cas et les gens doivent avoir la liberté de faire évoluer l’API avec les exigences futures, de manière rétrocompatible.

Notez que tout ce qui précède suppose que vous développiez une plate-forme utilisée et / ou étendue par d’autres personnes et non votre propre API où tous vos codes clients sont sous contrôle et peuvent donc être modifiés selon vos besoins.

Permet de le montrer sur l’une des Collection et Collections objects Java bien connues.


API: Collections est un ensemble de méthodes statiques utilitaires. Souvent, les classes représentant l’object API sont définies comme final car elles garantissent (au moment de la compilation) qu’aucun client ne puisse jamais “implémenter” cet object et qu’elles peuvent “appeler” ses méthodes statiques, par exemple

 Collections.emptySet(); 

Comme tous les clients “appellent” mais pas “implémentent” , les auteurs de JDK sont libres d’append de nouvelles méthodes dans l’object Collections dans la future version de JDK. Ils peuvent être sûrs qu’ils ne peuvent casser aucun client, même s’il y a probablement des millions d’utilisations.


SPI: Collection est une interface qui implique que chacun peut implémenter sa propre version. Ainsi, les auteurs de JDK ne peuvent pas y append de nouvelles méthodes, car cela briserait tous les clients qui ont écrit leur propre implémentation de Collection (*).

Lorsque vous devez append une méthode supplémentaire, vous devez généralement créer une nouvelle interface, par exemple Collection2 qui étend l’ancienne. Le client SPI peut alors décider de migrer vers la nouvelle version de SPI et de mettre en œuvre sa méthode supplémentaire ou de conserver l’ancienne.


Vous avez peut-être déjà vu le point. Si vous combinez les deux éléments en une seule classe, votre API est bloquée de tout ajout. C’est aussi la raison pour laquelle de bonnes API et Frameworks Java n’exposent pas abstract class car elles bloqueraient leur évolution future en ce qui concerne la compatibilité descendante.

Si quelque chose n’est toujours pas clair, je recommande de vérifier cette page qui explique plus en détail ce qui précède.


(*) Notez que ceci n’est vrai que jusqu’à ce que Java 1.8 qui introduit le concept de méthodes default défini dans une interface.