Qual è la differenza tra Service Provider Interface (SPI) e Application Programming Interface (API) ?
Più specificamente, per le librerie Java, cosa li rende un'API e / o SPI?
Qual è la differenza tra Service Provider Interface (SPI) e Application Programming Interface (API) ?
Più specificamente, per le librerie Java, cosa li rende un'API e / o SPI?
Risposte:
In altre parole, l'API ti dice cosa fa per te una specifica classe / metodo e l'SPI ti dice cosa devi fare per conformarti.
Solitamente API e SPI sono separati. Ad esempio, in JDBC la Driver
classe fa parte dell'SPI: se si desidera semplicemente utilizzare JDBC, non è necessario utilizzarlo direttamente, ma tutti coloro che implementano un driver JDBC devono implementare quella classe.
A volte si sovrappongono, tuttavia. L' Connection
interfaccia è sia SPI che API: la usi abitualmente quando usi un driver JDBC e deve essere implementata dallo sviluppatore del driver JDBC.
@SomeAnnotation
alla mia classe per farlo SomeAnnotation.class
rilevare da un framework, questa classe di annotazione sarebbe considerata parte della SPI, anche se non la sto estendendo o implementando tecnicamente?
Da Effective Java, 2nd Edition :
Un framework di fornitori di servizi è un sistema in cui più fornitori di servizi implementano un servizio e il sistema rende disponibili le implementazioni ai propri clienti, disaccoppiandole dalle implementazioni.
Esistono tre componenti essenziali di un framework di provider di servizi: un'interfaccia di servizio che i provider implementano; un'API di registrazione del provider, che il sistema utilizza per registrare le implementazioni, offrendo 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 provider. 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 service provider è un'interfaccia di service provider, che i provider implementano per creare istanze della loro implementazione del servizio. In assenza di un'interfaccia del fornitore di servizi, le implementazioni sono registrate in base al nome della classe e istanziate in modo riflessivo (elemento 53). Nel caso di JDBC, Connection svolge la parte dell'interfaccia del servizio, DriverManager.registerDriver è l'API di registrazione del provider, DriverManager.getConnection è l'API di accesso al servizio e Driver è l'interfaccia del provider di servizi.
Esistono numerose varianti del modello di framework 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, usando il modello Adapter [Gamma95, p. 139]. Ecco una semplice implementazione con un'interfaccia del 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<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 differenza tra API e SPI viene 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 di cercare un contesto è fornito in IntialContext. Questa classe utilizzerà internamente le interfacce SPI (utilizzando NamingManager) per implementazioni specifiche del provider.
Vedere l'architettura JNDI di seguito per una migliore comprensione.
API sta per Application Programming Interface, in cui API è un mezzo per accedere a un servizio / funzione fornito da un tipo di software o una piattaforma.
SPI è l' acronimo di Service Provider Interface, in cui SPI è il modo di iniettare, estendere o alterare il comportamento del software o di una piattaforma.
L'API è normalmente destinata ai client per accedere a un servizio e ha le seguenti proprietà:
-> L'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 client
-> Ma le API utilizzate una volta dai client non possono (e non dovrebbero) essere modificate / cancellate a meno che non ci siano comunicazioni appropriate, poiché è un completo degrado delle aspettative del cliente
L'SPI invece è destinato ai provider e ha le seguenti proprietà:
-> SPI è un modo per estendere / alterare il comportamento di un software o di una piattaforma (programmabile o programmatico)
-> L'evoluzione SPI è diversa dall'evoluzione API, nella rimozione SPI non è un problema
-> L'aggiunta di interfacce SPI causerà problemi e potrebbe interrompere le implementazioni esistenti
Per ulteriori spiegazioni, fare clic qui: Interfaccia fornitore di servizi
FAQ di NetBeans: Cos'è una SPI? In che cosa differisce da un'API?
API è un termine generale - un acronimo di 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 per le situazioni in cui una libreria fornisce classi chiamate dall'applicazione (o dalla libreria API) e che in genere cambiano 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 cassetta postale
- Il lato SPI se si sta fornendo un gestore di protocollo di filo per consentire a JavaMail di comunicare con un nuovo tipo di server, come un server di notizie o IMAP
Gli utenti dell'API raramente hanno bisogno di vedere o parlare con le classi SPI e viceversa.
In NetBeans, quando vedi il termine SPI, di solito si parla di classi che un modulo può iniettare in fase di esecuzione che consente a NetBeans di fare nuove cose. 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 si occupa dei file (il lato API) non deve preoccuparsi se esiste un sistema di controllo della versione o di cosa si tratta.
C'è un aspetto che non sembra essere evidenziato molto, ma è molto importante capire il ragionamento alla base dell'esistenza della divisione API / SPI.
La suddivisione API / SPI è richiesta solo quando ci si aspetta che la piattaforma evolva. Se scrivi un'API e "sai" che non richiederà alcun miglioramento futuro, non ci sono ragioni reali per dividere il codice in due parti (oltre a creare un design pulito degli oggetti).
Ma questo non è quasi mai il caso e le persone devono avere la libertà di evolvere l'API insieme ai requisiti futuri, in modo compatibile con le versioni precedenti.
Tieni presente che tutto quanto sopra presuppone che stai costruendo una piattaforma che altre persone utilizzano e / o estendono e non la tua API in cui hai tutto il codice client sotto controllo e quindi puoi eseguire il refactoring di cui hai bisogno.
Consente di mostrarlo su uno dei ben noti oggetti Java Collection
e Collections
.
API: Collections
è un insieme di metodi statici di utilità. Spesso le classi che rappresentano l'oggetto API sono definite in final
quanto garantiscono (al momento della compilazione) che nessun client può mai "implementare" quell'oggetto e che possono dipendere dal "chiamare" i suoi metodi statici, ad es.
Collections.emptySet();
Dal momento che tutti i clienti siano "chiamando" , ma non "di esecuzione" , autori di JDK sono liberi di aggiungere nuovi metodi in Collections
oggetto nella futura versione di JDK. Possono essere sicuri che non possa rompere nessun client, anche se probabilmente ci sono 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 esso poiché ciò spezzerebbe tutti i client che hanno scritto la propria Collection
implementazione (*).
In genere, quando è necessario aggiungere un metodo aggiuntivo, è necessario Collection2
creare una nuova interfaccia, ad esempio che estende quella 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 precedente.
Potresti già aver visto il punto. Se si combinano entrambi i pezzi in un'unica classe, l'API viene bloccata da eventuali aggiunte. Questo è anche il motivo per cui le buone API e Frameworks Java non si espongono abstract class
poiché bloccerebbero la loro evoluzione futura rispetto alla compatibilità con le versioni precedenti.
Se qualcosa non è ancora chiaro, ti consiglio di controllare questa pagina che spiega più in dettaglio quanto sopra.
(*) Nota questo è vero solo fino a Java 1.8 che introduce il concetto di default
metodi definiti in un'interfaccia.
Suppongo che uno SPI si inserisca in un sistema più grande implementando alcune funzionalità di un'API e quindi registrandosi come disponibile tramite i 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 utilizzo diretto.
L'interfaccia del fornitore di servizi è l'interfaccia di servizio che tutti i fornitori devono implementare. Se nessuna delle implementazioni di provider esistenti funziona per te, devi scrivere il tuo provider di servizi (implementando l'interfaccia di servizio) e registrarti da qualche parte (vedi il post utile di Roman).
Se stai riutilizzando l'implementazione del provider esistente dell'interfaccia del servizio, stai fondamentalmente usando l'API di quel particolare provider, che include tutti i metodi dell'interfaccia del servizio più alcuni metodi pubblici propri. Se si utilizzano metodi dell'API del provider al di fuori della SPI, si utilizzano funzionalità specifiche del provider.
Nel mondo Java, diverse tecnologie sono pensate per essere modulari e "collegabili" a un server delle applicazioni. C'è quindi una differenza tra
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 l'SPI per essere collegabile nell'app. server e fornire un'API da utilizzare dall'applicazione per l'utente finale. Un esempio di JCA è l' interfaccia ManagedConnection che fa parte dell'SPI e la connessione che fa parte dell'API dell'utente finale.