Differenza tra SPI e API?

Qual è la differenza tra Service Provider Interface (SPI) e Application Programming Interface (API) ?

Più specificamente, per le librerie Java, cosa le rende API e / o SPI?

  • L’API è la descrizione di classi / interfacce / metodi / … che chiami e utilizzi per raggiungere un objective, e
  • lo SPI è la descrizione di classi / interfacce / metodi / … che estendete e implementate per raggiungere un objective.

In altre parole, l’API ti dice quale class / metodo specifico fa per te, e l’SPI ti dice cosa devi fare per conformarti.

Di solito API e SPI sono separati. Ad esempio, in JDBC la class Driver fa parte dello SPI: se si desidera semplicemente utilizzare JDBC, non è necessario utilizzarlo direttamente, ma tutti coloro che implementano un driver JDBC devono implementare tale class.

A volte si sovrappongono, comunque. L’interfaccia di Connection è sia SPI che API: la si utilizza regolarmente quando si utilizza un driver JDBC e deve essere implementata dallo sviluppatore del driver JDBC.

Da efficace Java, seconda edizione :

Un framework di provider di servizi è un sistema in cui più provider di servizi implementano un servizio e il sistema rende disponibili le implementazioni ai propri clienti, disaccoppiandoli dalle implementazioni.

Esistono tre componenti essenziali di un framework di fornitore di servizi: un’interfaccia di servizio, che i provider implementano; un’API di registrazione del provider, che il sistema utilizza per registrare le implementazioni, dando ai clienti l’accesso ad esse; e un’API di accesso al servizio, che i client utilizzano per ottenere un’istanza del servizio. L’API di accesso al servizio in genere consente, ma non richiede al client di specificare alcuni criteri per la scelta di un fornitore. In assenza di tale specifica, l’API restituisce un’istanza di un’implementazione predefinita. L’API di accesso al servizio è la “fabbrica statica flessibile” che costituisce la base del framework del fornitore di servizi.

Un quarto componente facoltativo di un framework di provider di servizi è un’interfaccia di provider di servizi, che i provider implementano per creare istanze della loro implementazione del servizio. In assenza di un’interfaccia provider di servizi, le implementazioni sono registrate in base al nome della class e sono istanziate in modo riflessivo (Articolo 53). Nel caso di JDBC, Connection riproduce la parte dell’interfaccia di servizio, DriverManager.registerDriver è l’API di registrazione del provider, DriverManager.getConnection è l’API di accesso al servizio e Driver è l’interfaccia del fornitore di servizi.

Esistono numerose varianti del modello di struttura del fornitore di servizi. Ad esempio, l’API di accesso al servizio può restituire un’interfaccia di servizio più ricca di quella richiesta dal provider, utilizzando il modello Adapter [Gamma95, p. 139]. Ecco una semplice implementazione con un’interfaccia provider di servizi e un provider predefinito:

 // 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(); } } 

La differenza tra API e SPI arriva quando un’API fornisce anche alcune implementazioni concrete. In tal caso, il fornitore di servizi deve implementare alcune API (chiamate SPI)

Un esempio è JNDI:

JNDI fornisce interfacce e alcune classi per la ricerca del contesto. Il modo predefinito per cercare un contesto è fornito in IntialContext. Questa class internamente utilizzerà le interfacce SPI (usando NamingManager) per implementazioni specifiche del provider.

Vedere l’architettura JNDI di seguito per una migliore comprensione.

Inserisci qui la descrizione dell'immagine

API è l’ acronimo di Application Programming Interface, in cui l’API è un mezzo per accedere a un servizio / funzione fornita da qualche tipo di software o piattaforma.

SPI è l’ acronimo di Service Provider Interface, in cui SPI è un modo per iniettare, estendere o modificare il comportamento del software o di una piattaforma.

L’API è normalmente l’objective per i client di accedere a un servizio e ha le seguenti proprietà:

-> API è un modo programmatico di accedere a un servizio per ottenere un determinato comportamento o output

-> Dal punto di vista dell’evoluzione dell’API, l’aggiunta non è affatto un problema per i clienti

-> Ma le API una volta utilizzate dai client non possono (e non dovrebbero) essere alterate / cancellate a meno che non ci siano comunicazioni appropriate, dal momento che è un completo degrado delle aspettative del cliente

L’SPI sull’altra parte è mirato per i provider e ha le seguenti proprietà:

-> SPI è un modo per estendere / modificare il comportamento di un software o di una piattaforma (programmabile rispetto a programmatico)

-> L’evoluzione di SPI è diversa dall’evoluzione dell’API, nella rimozione SPI non è un problema

-> L’aggiunta di interfacce SPI causerà problemi e potrebbe interrompere le implementazioni esistenti

Per ulteriori spiegazioni clicca qui: Service Provider Interface

Domande frequenti su NetBeans: che cos’è un SPI? In che modo è diverso da un’API?

API è un termine generale – un acronimo per Application Programming Interface – significa qualcosa (in Java, di solito alcune classi Java) che espone un pezzo di software, che consente ad altri software di comunicare con esso.

SPI è l’acronimo di Service Provider Interface. È un sottoinsieme di tutte le cose che possono essere specifiche dell’API a situazioni in cui una libreria fornisce classi chiamate dall’applicazione (o libreria API) e che in genere modificano le cose che l’applicazione è in grado di fare.

L’esempio classico è JavaMail. La sua API ha due lati:

  • Il lato API – che chiami se stai scrivendo un client di posta o vuoi leggere una casella di posta
  • Lato SPI se si fornisce un gestore di protocollo filo per consentire a JavaMail di comunicare con un nuovo tipo di server, ad esempio una notizia o un server IMAP

Gli utenti dell’API raramente hanno bisogno di vedere o parlare con le classi SPI e viceversa.

In NetBeans, quando si vede il termine SPI, di solito si parla di classi che un modulo può iniettare in fase di runtime che consentono a NetBeans di fare cose nuove. Ad esempio, esiste un SPI generale per l’implementazione dei sistemi di controllo della versione. Diversi moduli forniscono implementazioni di tale SPI per CVS, Subversion, Mercurial e altri sistemi di controllo di revisione. Tuttavia, il codice che gestisce i file (lato API) non ha bisogno di preoccuparsi se esiste un sistema di controllo della versione o di cosa si tratta.

Suppongo che uno slot SPI in un sistema più grande implementando determinate funzionalità di un’API, e quindi si registra come disponibile tramite meccanismi di ricerca del servizio. Un’API viene utilizzata direttamente dal codice dell’applicazione dell’utente finale, ma può integrare componenti SPI. È la differenza tra incapsulamento e uso diretto.

L’interfaccia del service provider è l’interfaccia di servizio che tutti i provider devono implementare. Se nessuna delle implementazioni esistenti del provider funziona per te, devi scrivere il tuo fornitore di servizi (implementando l’interfaccia del servizio) e registrarti da qualche parte (vedi il post utile di Roman).

Se si riutilizza l’implementazione del provider esistente dell’interfaccia del servizio, si utilizza fondamentalmente l’API di quel particolare provider, che include tutti i metodi dell’interfaccia del servizio più alcuni metodi pubblici propri. Se stai utilizzando i metodi dell’API provider al di fuori della SPI, stai utilizzando funzionalità specifiche del provider.

Nel mondo Java, diverse tecnologie sono pensate per essere modulari e “inseribili” in un application server. C’è quindi una differenza tra

  • il server delle applicazioni
    • [SPI]
  • la tecnologia collegabile
    • [API]
  • l’applicazione per l’utente finale

Due esempi di tali tecnologie sono JTA (il gestore delle transazioni) e JCA (adattatore per JMS o database). Ma ce ne sono altri.

L’implementatore di tale tecnologia collegabile deve quindi implementare lo SPI per essere inserito nell’app. server e fornire un’API da utilizzare dall’applicazione dell’utente finale. Un esempio di JCA è l’interfaccia ManagedConnection che fa parte dello SPI e la Connection che fa parte dell’API dell’utente finale.

C’è un aspetto che non sembra essere evidenziato molto, ma è molto importante capire il ragionamento dietro l’esistenza della divisione API / SPI.

La divisione API / SPI è richiesta solo quando si prevede che la piattaforma evolva. Se si scrive un’API e “si sa”, non sarà necessario alcun miglioramento futuro in assoluto, non vi sono motivi reali per suddividere il codice nelle due parti (oltre a rendere la progettazione degli oggetti pulita).

Ma questo non è quasi mai il caso e le persone hanno bisogno di avere la libertà di evolvere l’API insieme ai requisiti futuri – in un modo compatibile con le versioni precedenti.

Nota che tutto quanto sopra presuppone che tu stia costruendo una piattaforma che altre persone usano e / o estendono e non la tua API in cui hai tutto il codice cliente sotto controllo e quindi puoi refactoring di cui hai bisogno.

Lo mostriamo su una delle ben note Collection e Collections oggetti Java.


API: Collections è un insieme di metodi statici di utilità. Spesso le classi che rappresentano l’object API sono definite come final in quanto garantisce (al momento della compilazione) che nessun client può mai “implementare” quell’object e possono dipendere dal “chiamare” i suoi metodi statici, ad es.

 Collections.emptySet(); 

Poiché tutti i client “chiamano” ma non “implementano” , gli autori di JDK sono liberi di aggiungere nuovi metodi nell’object Collections nella futura versione di JDK. Possono essere sicuri che non possano rompere nessun cliente, anche se ci sono probabilmente milioni di usi.


SPI: Collection è un’interfaccia che implica che chiunque può implementare la propria versione di esso. Pertanto, gli autori di JDK non possono aggiungere nuovi metodi in quanto potrebbero rompere tutti i client che hanno scritto la propria implementazione Collection (*).

Tipicamente quando è necessario aggiungere un altro metodo, è necessario creare una nuova interfaccia, ad es. Collection2 che estenda il precedente. Il client SPI può quindi decidere se migrare alla nuova versione di SPI e implementare il suo metodo aggiuntivo o se attenersi a quello più vecchio.


Potresti aver già visto il punto. Se unisci entrambi i pezzi in una singola class, la tua API viene bloccata da qualsiasi aggiunta. Questo è anche il motivo per cui le buone API e i framework Java non espongono la abstract class poiché bloccerebbero la loro evoluzione futura rispetto alla retrocompatibilità.

Se qualcosa non è ancora chiaro, ti consiglio di controllare questa pagina che spiega più dettagliatamente quanto sopra.


(*) Nota questo è vero solo fino a Java 1.8 che introduce il concetto di metodi default definiti in un’interfaccia.