Diferença entre SPI e API?

Respostas:

395
  • A API é a descrição das classes / interfaces / métodos / ... que você chama e usa para atingir uma meta e
  • o SPI é a descrição das classes / interfaces / métodos / ... que você estende e implementa para atingir uma meta.

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 Driverclasse 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 Connectioninterface 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.

Joachim Sauer
fonte
parece correto. seu justo que as linhas entre SPI & API pode ser um pouco cinzenta como a maioria API tem classes abstratas / interfaces para o utilizador implementar para fazer as coisas bem ...
kctang
1
@ koss: mais API? Eu sei o que você quer dizer, mas não vejo muito essas coisas.
Joachim Sauer
2
A API é mais relevante para os desenvolvedores, enquanto o SPI é para os fornecedores.
Azfar Niaz
7
@AzfarNiaz: bem, uma vez que os desenvolvedores fornecedores empregam para construir seus produtos tanto são relevantes para os desenvolvedores ;-)
Joachim Sauer
Em Java, as anotações fazem parte de um SPI? Por exemplo, se eu tiver que adicionar @SomeAnnotationà minha classe para selecioná-la por alguma estrutura, essa classe de anotação SomeAnnotation.classserá considerada parte do SPI, mesmo que eu não a esteja estendendo ou implementando tecnicamente?
22616 Adam Burley
59

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();
    }
}
romano
fonte
3
obrigado pela descrição muito agradável na estrutura do provedor de serviços. isso será útil para saber. no entanto, não descreve claramente "diferença" entre api & spi por isso não vou colocar uma marca aqui ... ;-)
kctang
23

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.

Digite a descrição da imagem aqui

Sandeep Jindal
fonte
22

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

Venkata Aditya Pavan
fonte
12

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 é.

Ondra Žižka
fonte
5

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 Collectione 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 finalasseguram (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 Collectionsobjeto 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 Collectionimplementação (*).

Normalmente, quando é necessário adicionar um método adicional, é necessário criar uma nova interface, por exemplo, Collection2que 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 defaultmétodos definidos em uma interface.

Martin Janíček
fonte
4

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.

Chris Dennett
fonte
obrigado pela resposta chris. algum exemplo de bibliotecas Java existentes (ou seja, Servlet, JDBC etc.)? ... como ele os torna API / SPI. pode ser difícil visualizar a diferença apenas com a descrição.
kctang
1
Uma API é JDBC, uma SPI para JDBC é a interface do conector de banco de dados que os desenvolvedores de SPI podem usar para criar novos conectores de banco de dados que o desenvolvedor pode selecionar para uso.
precisa
4

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.

tapasvi
fonte
2

No mundo Java, diferentes tecnologias devem ser modulares e "conectáveis" em um servidor de aplicativos. Existe então uma diferença entre

  • o servidor de aplicativos
    • [SPI]
  • a tecnologia conectável
    • [API]
  • o aplicativo do usuário final

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.

ewernli
fonte