Qual é a diferença entre Service Provider Interface (SPI) e Application Programming Interface (API) ?
Mais especificamente, para bibliotecas Java, o que as torna uma API e / ou SPI?
Qual é a diferença entre Service Provider Interface (SPI) e Application Programming Interface (API) ?
Mais especificamente, para bibliotecas Java, o que as torna uma API e / ou SPI?
Respostas:
Em outras palavras, a API informa o que uma classe / método específico faz por você, e o SPI informa o que você deve fazer para estar em conformidade.
Normalmente, API e SPI são separados. Por exemplo, no JDBC, a Driver
classe faz parte do SPI: se você simplesmente deseja usar o JDBC, não precisa usá-lo diretamente, mas todos que implementam um driver JDBC devem implementar essa classe.
Às vezes, eles se sobrepõem. A Connection
interface de é tanto SPI e API: Você usá-lo rotineiramente quando você usa um driver JDBC e ele precisa ser implementado pelo desenvolvedor do driver JDBC.
@SomeAnnotation
à minha classe para selecioná-la por alguma estrutura, essa classe de anotação SomeAnnotation.class
será considerada parte do SPI, mesmo que eu não a esteja estendendo ou implementando tecnicamente?
Do Effective Java, 2ª Edição :
Uma estrutura de provedor de serviços é um sistema no qual vários provedores de serviços implementam um serviço, e o sistema disponibiliza as implementações para seus clientes, separando-as das implementações.
Existem três componentes essenciais de uma estrutura de provedor de serviços: uma interface de serviço, implementada pelos provedores; uma API de registro de provedor, que o sistema usa para registrar implementações, dando aos clientes acesso a elas; e uma API de acesso ao serviço, usada pelos clientes para obter uma instância do serviço. A API de acesso ao serviço normalmente permite, mas não exige que o cliente especifique alguns critérios para escolher um provedor. Na ausência de tal especificação, a API retorna uma instância de uma implementação padrão. A API de acesso ao serviço é a "fábrica estática flexível" que forma a base da estrutura do provedor de serviços.
Um quarto componente opcional de uma estrutura de provedor de serviços é uma interface de provedor de serviços, que os provedores implementam para criar instâncias de sua implementação de serviço. Na ausência de uma interface de provedor de serviços, as implementações são registradas pelo nome da classe e instanciadas de forma reflexiva (Item 53). No caso do JDBC, o Connection faz parte da interface de serviço, DriverManager.registerDriver é a API de registro do provedor, DriverManager.getConnection é a API de acesso ao serviço e Driver é a interface do provedor de serviços.
Existem inúmeras variantes do padrão de estrutura do provedor de serviços. Por exemplo, a API de acesso ao serviço pode retornar uma interface de serviço mais rica que a exigida pelo provedor, usando o padrão do adaptador [Gamma95, p. 139] Aqui está uma implementação simples com uma interface de provedor de serviços e um provedor padrão:
// 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();
}
}
A diferença entre API e SPI ocorre quando uma API fornece adicionalmente algumas implementações concretas. Nesse caso, o provedor de serviços precisa implementar algumas APIs (chamadas SPI)
Um exemplo é JNDI:
O JNDI fornece interfaces e algumas classes para pesquisa de contexto. A maneira padrão de procurar um contexto é fornecida no IntialContext. Essa classe internamente usará interfaces SPI (usando o NamingManager) para implementações específicas do provedor.
Veja a arquitetura JNDI abaixo para entender melhor.
API significa Application Programming Interface, onde API é um meio de acessar um serviço / função fornecida por algum tipo de software ou plataforma.
SPI significa Service Provider Interface, onde SPI é uma maneira de injetar, estender ou alterar o comportamento de software ou plataforma.
A API é normalmente destinada aos clientes para acessar um serviço e possui as seguintes propriedades:
-> API é uma maneira programática de acessar um serviço para obter um determinado comportamento ou saída
-> Do ponto de vista da evolução da API, a adição não é problema para os clientes
-> Mas as APIs, uma vez utilizadas pelos clientes, não podem (e não devem) ser alteradas / excluídas, a menos que haja uma comunicação adequada, pois é uma degradação completa da expectativa do cliente
O SPI, por outro lado, é direcionado a fornecedores e possui as seguintes propriedades:
-> SPI é uma maneira de estender / alterar o comportamento de um software ou plataforma (programável versus programático)
-> A evolução do SPI é diferente da evolução da API, na remoção do SPI não é um problema
-> A adição de interfaces SPI causará problemas e poderá interromper as implementações existentes
Para obter mais explicações, clique aqui: Interface do Provedor de Serviços
Perguntas frequentes do NetBeans: O que é um SPI? Qual é a diferença de uma API?
API é um termo geral - um acrônimo para Application Programming Interface - significa algo (em Java, geralmente algumas classes Java) que um software expõe, que permite que outro software se comunique com ele.
SPI significa Service Provider Interface. É um subconjunto de todas as coisas que podem ser API específicas para situações em que uma biblioteca está fornecendo classes chamadas pelo aplicativo (ou biblioteca de API) e que normalmente alteram as coisas que o aplicativo é capaz de fazer.
O exemplo clássico é JavaMail. Sua API tem dois lados:
- O lado da API - para o qual você liga se estiver escrevendo um cliente de email ou quiser ler uma caixa de correio
- O lado SPI se você estiver fornecendo um manipulador de protocolo de fio para permitir que o JavaMail fale com um novo tipo de servidor, como um servidor de notícias ou IMAP
Os usuários da API raramente precisam ver ou conversar com as classes SPI e vice-versa.
No NetBeans, quando você vê o termo SPI, geralmente se trata de classes que um módulo pode injetar em tempo de execução, o que permite ao NetBeans fazer coisas novas. Por exemplo, existe um SPI geral para implementar sistemas de controle de versão. Diferentes módulos fornecem implementações desse SPI para CVS, Subversion, Mercurial e outros sistemas de controle de revisão. No entanto, o código que lida com arquivos (o lado da API) não precisa se importar se existe um sistema de controle de versão ou o que é.
Há um aspecto que parece pouco destacado, mas é muito importante entender o raciocínio por trás da existência da divisão API / SPI.
A divisão API / SPI é necessária apenas quando a plataforma deve evoluir. Se você escreve uma API e "sabe" que ela nunca exigirá melhorias futuras, não há motivos reais para dividir seu código nas duas partes (além de criar um design de objeto limpo).
Mas esse quase nunca é o caso e as pessoas precisam ter liberdade para evoluir a API junto com os requisitos futuros - de uma maneira compatível com versões anteriores.
Observe que todas as opções acima pressupõem que você está construindo uma plataforma que outras pessoas usam e / ou estendem e não sua própria API, na qual você tem todo o código do cliente sob controle e, portanto, pode refatorar conforme necessário.
Vamos mostrá-lo em um dos objetos Java Collection
e Collections
.
API: Collections
é um conjunto de métodos estáticos de utilidade. Freqüentemente, as classes que representam o objeto da API são definidas como final
asseguram (no momento da compilação) que nenhum cliente possa "implementar" esse objeto e que elas dependam de "chamar" seus métodos estáticos, por exemplo
Collections.emptySet();
Como todos os clientes estão "chamando", mas não "implementando" , os autores do JDK podem adicionar novos métodos ao Collections
objeto na versão futura do JDK. Eles podem ter certeza de que não podem prejudicar nenhum cliente, mesmo que haja provavelmente milhões de usos.
SPI: Collection
é uma interface que implica que qualquer pessoa pode implementar sua própria versão. Portanto, os autores do JDK não podem adicionar novos métodos, pois isso quebraria todos os clientes que escreveram sua própria Collection
implementação (*).
Normalmente, quando é necessário adicionar um método adicional, é necessário criar uma nova interface, por exemplo, Collection2
que estende a anterior. O cliente SPI pode decidir se deseja migrar para a nova versão do SPI e implementar seu método adicional ou se deseja continuar com o anterior.
Você já deve ter visto o ponto. Se você combinar as duas partes em uma única classe, sua API será bloqueada de quaisquer adições. Essa também é a razão pela qual as boas APIs e estruturas Java não são expostas abstract class
, pois bloqueariam sua evolução futura com relação à compatibilidade com versões anteriores.
Se algo ainda não estiver claro, recomendo verificar esta página que explica o acima em mais detalhes.
(*) Observe que isso é verdade apenas até o Java 1.8, que introduz o conceito de default
métodos definidos em uma interface.
Suponho que um SPI se encaixe em um sistema maior implementando certos recursos de uma API e, em seguida, registrando-se como disponível através de mecanismos de pesquisa de serviço. Uma API é usada diretamente pelo código do aplicativo do usuário final, mas pode integrar componentes SPI. É a diferença entre encapsulamento e uso direto.
A interface do provedor de serviços é a interface de serviço que todos os provedores devem implementar. Se nenhuma das implementações de provedores existentes funcionar para você, você precisa escrever seu próprio provedor de serviços (implementando a interface de serviço) e se registrar em algum lugar (consulte a publicação útil de Roman).
Se você está reutilizando a implementação de provedor existente da interface de serviço, está basicamente usando a API desse provedor específico, que inclui todos os métodos de interface de serviço, além de alguns métodos públicos próprios. Se você estiver usando métodos da API do provedor fora do SPI, estará usando recursos específicos do provedor.
No mundo Java, diferentes tecnologias devem ser modulares e "conectáveis" em um servidor de aplicativos. Existe então uma diferença entre
Dois exemplos dessas tecnologias são JTA (o gerenciador de transações) e JCA (adaptador para JMS ou banco de dados). Mas existem outros.
O implementador de uma tecnologia tão conectável deve implementar o SPI para ser plugável no aplicativo. servidor e forneça uma API a ser usada pelo aplicativo do usuário final. Um exemplo da JCA é a interface ManagedConnection que faz parte da SPI e a Conexão que faz parte da API do usuário final.