Quelle est la différence entre l' interface de fournisseur de services (SPI) et l' interface de programmation d'applications (API) ?
Plus précisément, pour les bibliothèques Java, qu'est-ce qui en fait une API et / ou SPI?
Quelle est la différence entre l' interface de fournisseur de services (SPI) et l' interface de programmation d'applications (API) ?
Plus précisément, pour les bibliothèques Java, qu'est-ce qui en fait une API et / ou SPI?
Réponses:
Autrement dit, l'API vous indique ce qu'une classe / méthode spécifique fait pour vous et le SPI vous indique ce que vous devez faire pour vous conformer.
Généralement, l'API et le SPI sont séparés. Par exemple, dans JDBC, la Driver
classe fait partie du SPI: si vous voulez 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, cependant, ils se chevauchent. L' Connection
interface est à la fois SPI et API: vous l'utilisez régulièrement lorsque vous utilisez un pilote JDBC et elle doit être implémentée par le développeur du pilote JDBC.
@SomeAnnotation
à ma classe pour qu'elle soit récupérée par un cadre, cette classe d'annotations SomeAnnotation.class
serait-elle considérée comme faisant partie du SPI, même si je ne l'étends ou ne l'implémente pas techniquement?
Extrait de Effective Java, 2nd Edition :
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, les découplant des implémentations.
Il existe trois composants essentiels d'une structure de fournisseur de services: une interface de service, que les fournisseurs mettent en œuvre; une API d'enregistrement de fournisseur, que le système utilise pour enregistrer les implémentations, permettant aux clients d'y accéder; et une API d'accès au service, que les clients utilisent pour obtenir une instance du service. L'API d'accès au service permet généralement au client de spécifier certains critères pour choisir un fournisseur, mais ne l'exige pas. En l'absence d'une telle spécification, l'API renvoie une instance d'une implémentation par défaut. L'API d'accès aux services est la «fabrique statique flexible» qui constitue la base du cadre du fournisseur de services.
Un quatriè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 (article 53). Dans le cas de JDBC, Connection joue le rôle de l'interface de service, DriverManager.registerDriver est l'API d'enregistrement du fournisseur, DriverManager.getConnection est l'API d'accès au service et Driver est l'interface du fournisseur de service.
Il existe de nombreuses variantes du modèle de structure de fournisseur de services. Par exemple, l'API d'accès au service peut renvoyer une interface de service plus riche que celle requise 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<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();
}
}
La différence entre l'API et le SPI survient lorsqu'une API fournit en outre 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 certaines classes pour la recherche de contexte. La façon par défaut de rechercher un contexte est fournie dans IntialContext. Cette classe utilise en interne des interfaces SPI (à l'aide de NamingManager) pour les implémentations spécifiques au fournisseur.
Voir l'architecture JNDI ci-dessous pour une meilleure compréhension.
API signifie Application Programming Interface, où API est un moyen d'accéder à un service / fonction fourni par une sorte de logiciel ou une plate-forme.
SPI signifie Service Provider Interface, où SPI est un moyen 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 elle a les propriétés suivantes:
-> L'API est un moyen programmatique d'accéder à un service pour obtenir un certain comportement ou sortie
-> Du point de vue de l'évolution de l'API, l'ajout ne pose aucun problème aux clients
-> Mais une fois que les API sont utilisées par les clients, elles ne peuvent (et ne devraient pas) être modifiées / supprimées à moins qu'il y ait une communication appropriée, car c'est une dégradation complète des attentes du client
SPI, d'autre part, est destiné aux fournisseurs et possède les propriétés suivantes:
-> SPI est un moyen d'étendre / modifier le comportement d'un logiciel ou d'une plateforme (programmable vs 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 entraînera des problèmes et pourrait 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-elle différente d'une API?
API est un terme général - un acronyme pour Application Programming Interface - cela signifie quelque chose (en Java, généralement certaines classes Java) qu'un logiciel expose, ce qui permet à d'autres logiciels de communiquer avec lui.
SPI est l'abréviation de Service Provider Interface. Il s'agit d'un sous-ensemble de toutes les choses qui peuvent être spécifiques à l'API dans les situations où une bibliothèque fournit des classes qui sont appelées par l'application (ou la bibliothèque d'API) et qui modifient généralement les choses 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 souhaitez lire une boîte aux lettres
- Le côté SPI si vous fournissez un gestionnaire de protocole filaire pour permettre à JavaMail de parler à un nouveau type de serveur, tel qu'un serveur d'actualités ou IMAP
Les utilisateurs de l'API ont rarement besoin de voir ou de parler aux classes SPI, et vice-versa.
Dans NetBeans, lorsque vous voyez le terme SPI, il s'agit généralement de classes qu'un module peut injecter au moment de l'exécution, ce qui permet à NetBeans de faire de nouvelles choses. Par exemple, il existe un SPI général pour l'implémentation des systèmes de contrôle de version. Différents modules fournissent des implémentations de ce SPI pour CVS, Subversion, Mercurial et d'autres systèmes de contrôle de révision. Cependant, le code qui traite des fichiers (du côté de l'API) n'a pas besoin de se soucier s'il existe un système de contrôle de version ou de quoi il s'agit.
Il y a un aspect qui ne semble pas être mis en évidence mais qui est très important pour comprendre le raisonnement derrière l'existence de la division API / SPI.
La répartition API / SPI n'est requise que lorsque la plate-forme devrait évoluer. Si vous écrivez une API et que vous "savez" qu'elle ne nécessitera jamais d'améliorations futures, il n'y a aucune raison réelle de diviser votre code en deux parties (en plus de créer une conception d'objet propre).
Mais ce n'est presque jamais le cas et les gens doivent avoir la liberté d'évoluer API avec les exigences futures - d'une manière rétrocompatible.
Notez que tout ce qui précède suppose que vous construisez une plate-forme que d'autres personnes utilisent et / ou étendent et non votre propre API où vous avez tout le code client sous contrôle et pouvez donc refactoriser à votre guise.
Permet de le montrer sur l'un des objets Java bien connus Collection
et Collections
.
API: Collections
est un ensemble de méthodes statiques utilitaires. Souvent, les classes représentant un objet API sont définies car final
elles garantissent (au moment de la compilation) qu'aucun client ne peut jamais "implémenter" cet objet et qu'elles peuvent dépendre de "l'appel" de ses méthodes statiques, par exemple
Collections.emptySet();
Étant donné que tous les clients "appellent" mais pas "implémentent" , les auteurs de JDK sont libres d'ajouter de nouvelles méthodes dans l' Collections
objet dans la future version de JDK. Ils peuvent être sûrs que cela ne peut briser aucun client, même s'il y a probablement des millions d'utilisations.
SPI: Collection
est une interface qui implique que n'importe qui peut en implémenter sa propre version. Ainsi, les auteurs de JDK ne peuvent pas y ajouter de nouvelles méthodes car cela briserait tous les clients qui ont écrit leur propre Collection
implémentation (*).
Généralement, lorsqu'une méthode supplémentaire doit être ajoutée, une nouvelle interface, par exemple Collection2
qui étend l'ancienne, doit être créée. Le client SPI peut alors décider de migrer vers la nouvelle version de SPI et d'implémenter sa méthode supplémentaire ou de s'en tenir à l'ancienne.
Vous avez peut-être déjà vu le point. Si vous combinez les deux pièces ensemble dans une seule classe, votre API est bloquée de tout ajout. C'est également la raison pour laquelle les bonnes API et cadres Java ne s'exposent pas abstract class
car ils bloqueraient leur évolution future en ce qui concerne la compatibilité descendante.
Si quelque chose n'est toujours pas clair, je vous recommande de consulter cette page qui explique ce qui précède plus en détail.
(*) Notez que cela n'est vrai que jusqu'à Java 1.8 qui introduit le concept de default
méthodes définies dans une interface.
Je suppose qu'un SPI se place dans un système plus grand en implémentant certaines fonctionnalités d'une API, puis en s'inscrivant 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 des implémentations de fournisseurs existantes ne fonctionne pour vous, vous devez écrire votre propre fournisseur de services (implémenter l'interface de service) et vous inscrire quelque part (voir le billet utile de Roman).
Si vous réutilisez l'implémentation de fournisseur de services existante de l'interface de service, vous utilisez essentiellement l'API de ce fournisseur particulier, qui inclut toutes les méthodes de l'interface de service ainsi que quelques méthodes publiques. Si vous utilisez des méthodes d'API de fournisseur en dehors du SPI, vous utilisez des fonctionnalités spécifiques au fournisseur.
Dans le monde Java, différentes technologies sont censées être modulaires et «enfichables» dans un serveur d'applications. Il y a alors une différence entre
JTA (le gestionnaire de transactions) et JCA (adaptateur pour JMS ou base de données) sont deux exemples de ces technologies. Mais il y en a d'autres.
Le réalisateur d'une telle technologie enfichable doit ensuite implémenter le SPI pour être enfichable dans l'application. serveur et fournir une API à utiliser par l'application de l'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.