¿Diferencia entre SPI y API?

Respuestas:

395
  • La API es la descripción de clases / interfaces / métodos / ... que llama y usa para lograr un objetivo, y
  • El SPI es la descripción de clases / interfaces / métodos / ... que usted extiende e implementa para lograr un objetivo.

Dicho de otra manera, la API le dice lo que una clase / método específico hace por usted, y el SPI le dice qué debe hacer para cumplir.

Por lo general, API y SPI están separados. Por ejemplo, en JDBC la Driverclase es parte del SPI: si simplemente desea usar JDBC, no necesita usarlo directamente, pero todos los que implementen un controlador JDBC deben implementar esa clase.

A veces se superponen, sin embargo. La Connectioninterfaz es a la vez SPI y API: se usa de forma rutinaria cuando se usa un controlador JDBC y el desarrollador del controlador JDBC debe implementarla.

Joachim Sauer
fuente
suena bien. es sólo que las líneas entre el SPI y API puede ser un poco gris como la mayoría API tiene clases abstractas / interfaces para su usuario para poner en práctica para hacer las cosas así ...
kctang
1
@koss: la mayoría de las API? Sé lo que quieres decir, pero no veo mucho esas cosas.
Joachim Sauer
2
API es más relevante para los desarrolladores, mientras que SPI es para los proveedores.
Azfar Niaz
77
@AzfarNiaz: bueno, dado que los vendedores emplean desarrolladores para construir sus productos, ambos son relevantes para los desarrolladores ;-)
Joachim Sauer
En Java, ¿son las anotaciones parte de un SPI? Por ejemplo, si tengo que agregar @SomeAnnotationa mi clase para que algún marco lo recoja, ¿ SomeAnnotation.classse consideraría esta clase de anotación parte del SPI, aunque técnicamente no la extienda o implemente?
Adam Burley
59

De Java efectivo, 2da edición :

Un marco de proveedor de servicios es un sistema en el que múltiples proveedores de servicios implementan un servicio, y el sistema pone las implementaciones a disposición de sus clientes, desacoplándolos de las implementaciones.

Hay tres componentes esenciales de un marco de proveedor de servicios: una interfaz de servicio, que los proveedores implementan; una API de registro de proveedores, que el sistema usa para registrar implementaciones, que les da acceso a los clientes; y una API de acceso al servicio, que los clientes usan para obtener una instancia del servicio. La API de acceso al servicio generalmente permite, pero no requiere, que el cliente especifique algunos criterios para elegir un proveedor. En ausencia de tal especificación, la API devuelve una instancia de una implementación predeterminada. La API de acceso al servicio es la "fábrica estática flexible" que forma la base del marco del proveedor de servicios.

Un cuarto componente opcional de un marco de proveedor de servicios es una interfaz de proveedor de servicios, que los proveedores implementan para crear instancias de su implementación de servicios. En ausencia de una interfaz de proveedor de servicios, las implementaciones se registran por nombre de clase y se instancian de forma reflexiva (Elemento 53). En el caso de JDBC, Connection desempeña el papel de la interfaz de servicio, DriverManager.registerDriver es la API de registro del proveedor, DriverManager.getConnection es la API de acceso al servicio y Driver es la interfaz del proveedor de servicios.

Existen numerosas variantes del patrón de marco del proveedor de servicios. Por ejemplo, la API de acceso al servicio puede devolver una interfaz de servicio más rica que la requerida por el proveedor, utilizando el patrón Adaptador [Gamma95, p. 139]. Aquí hay una implementación simple con una interfaz de proveedor de servicios y un proveedor predeterminado:

// 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
fuente
3
gracias por la muy buena descripción del marco del proveedor de servicios. Esto será útil para saber. sin embargo, no describe claramente la "diferencia" entre el API y SPI, así que no voy a poner un tilde aquí ... ;-)
kctang
23

La diferencia entre API y SPI se produce cuando una API además proporciona algunas implementaciones concretas. En ese caso, el proveedor de servicios tiene que implementar algunas API (llamadas SPI)

Un ejemplo es JNDI:

JNDI proporciona interfaces y algunas clases para la búsqueda de contexto. La forma predeterminada de buscar un contexto se proporciona en IntialContext. Esta clase internamente usará interfaces SPI (usando NamingManager) para implementaciones específicas del proveedor.

Vea la arquitectura JNDI a continuación para una mejor comprensión.

Ingrese la descripción de la imagen aquí

Sandeep Jindal
fuente
22

API significa interfaz de programación de aplicaciones, donde API es un medio para acceder a un servicio / función proporcionado por algún tipo de software o plataforma.

SPI significa Interfaz de proveedor de servicios, donde SPI es una forma de inyectar, extender o alterar el comportamiento del software o una plataforma.

La API normalmente es el objetivo para que los clientes accedan a un servicio y tiene las siguientes propiedades:

-> API es una forma programática de acceder a un servicio para lograr un determinado comportamiento o resultado

-> Desde el punto de vista de la evolución de la API, la adición no es un problema para los clientes

-> Pero las API, una vez utilizadas por los clientes, no pueden (y no deben) ser alteradas / eliminadas a menos que haya una comunicación adecuada, ya que es una degradación completa de las expectativas del cliente

SPI por otro lado está dirigido a proveedores y tiene las siguientes propiedades:

-> SPI es una forma de extender / alterar el comportamiento de un software o una plataforma (programable vs. programático)

-> La evolución de SPI es diferente de la evolución de API, en la eliminación de SPI no es un problema

-> La adición de interfaces SPI causará problemas y puede romper las implementaciones existentes

Para más explicaciones, haga clic aquí: Interfaz de proveedor de servicios

Venkata Aditya Pavan
fuente
12

Preguntas frecuentes de NetBeans: ¿Qué es un SPI? ¿Cómo es diferente de una API?

API es un término general, un acrónimo de interfaz de programación de aplicaciones, significa algo (en Java, generalmente algunas clases de Java) que expone una pieza de software, lo que permite que otro software se comunique con ella.

SPI significa interfaz de proveedor de servicios. Es un subconjunto de todas las cosas que pueden ser específicas de la API para situaciones en las que una biblioteca proporciona clases a las que llama la aplicación (o la biblioteca de la API) y que normalmente cambian las cosas que la aplicación puede hacer.

El ejemplo clásico es JavaMail. Su API tiene dos lados:

  • El lado de la API, al que puede llamar si está escribiendo un cliente de correo o desea leer un buzón
  • El lado SPI si está proporcionando un controlador de protocolo de cable para permitir que JavaMail hable con un nuevo tipo de servidor, como un servidor de noticias o IMAP

Los usuarios de la API rara vez necesitan ver o hablar con las clases SPI, y viceversa.

En NetBeans, cuando ve el término SPI, generalmente se trata de clases que un módulo puede inyectar en tiempo de ejecución que permiten a NetBeans hacer cosas nuevas. Por ejemplo, hay un SPI general para implementar sistemas de control de versiones. Los diferentes módulos proporcionan implementaciones de ese SPI para CVS, Subversion, Mercurial y otros sistemas de control de revisión. Sin embargo, el código que trata con archivos (en el lado de la API) no necesita preocuparse si hay un sistema de control de versiones o lo que es.

Ondra Žižka
fuente
5

Hay un aspecto que no parece destacarse mucho, pero es muy importante para entender el razonamiento detrás de la existencia de la división API / SPI.

La división API / SPI solo se requiere cuando se espera que la plataforma evolucione. Si escribe una API y "sabe" que no requerirá ninguna mejora futura, no hay razones reales para dividir su código en las dos partes (además de hacer un diseño de objeto limpio).

Pero este casi nunca es el caso y las personas necesitan tener la libertad de evolucionar la API junto con los requisitos futuros, de una manera compatible con versiones anteriores.

Tenga en cuenta que todo lo anterior supone que está construyendo una plataforma que otras personas usan y / o extienden y no su propia API donde tiene todo el código del cliente bajo control y, por lo tanto, puede refactorizar como lo necesite.

Vamos a mostrarlo en uno de los objetos Java Collectiony conocidos Collections.


API: Collections es un conjunto de métodos estáticos de utilidad. A menudo, las clases que representan el objeto API se definen finalporque asegura (en el momento de la compilación) que ningún cliente puede "implementar" ese objeto y puede depender de "llamar" a sus métodos estáticos, por ejemplo

Collections.emptySet();

Como todos los clientes están "llamando" pero no "implementando" , los autores de JDK son libres de agregar nuevos métodos al Collectionsobjeto en la versión futura de JDK. Pueden estar seguros de que no puede afectar a ningún cliente, incluso si probablemente haya millones de usos.


SPI: Collection es una interfaz que implica que cualquiera puede implementar su propia versión. Por lo tanto, los autores de JDK no pueden agregar nuevos métodos, ya que rompería a todos los clientes que escribieron su propia Collectionimplementación (*).

Por lo general, cuando se requiere agregar un método adicional, se debe crear una nueva interfaz, por ejemplo, Collection2que amplíe la anterior. El cliente SPI puede decidir si migrar a la nueva versión de SPI e implementar su método adicional o si se queda con la anterior.


Puede que ya hayas visto el punto. Si combina ambas piezas juntas en una sola clase, su API se bloquea de cualquier adición. Esa es también la razón por la cual las buenas API y Frameworks de Java no se exponen, abstract classya que bloquearían su evolución futura con respecto a la compatibilidad con versiones anteriores.

Si algo aún no está claro, recomiendo consultar esta página que explica lo anterior con más detalle.


(*) Tenga en cuenta que esto es cierto solo hasta Java 1.8, que introduce el concepto de defaultmétodos definidos en una interfaz.

Martin Janíček
fuente
4

Supongo que un SPI se inserta en un sistema más grande implementando ciertas características de una API y luego registrándose como disponible a través de mecanismos de búsqueda de servicios. El código de la aplicación del usuario final utiliza una API directamente, pero puede integrar componentes SPI. Es la diferencia entre encapsulación y uso directo.

Chris Dennett
fuente
Gracias por la respuesta Chris. ¿Algún ejemplo de las bibliotecas existentes de Java (es decir, Servlet, JDBC, etc.)? ... como cómo los hace API / SPI. Puede ser difícil visualizar la diferencia solo con la descripción.
kctang
1
Una API es JDBC, un SPI para JDBC es la interfaz de conector de base de datos que los desarrolladores de SPI pueden usar para crear nuevos conectores de base de datos que el desarrollador puede seleccionar para su uso.
Chris Dennett
4

La interfaz del proveedor de servicios es la interfaz de servicio que todos los proveedores deben implementar. Si ninguna de las implementaciones de proveedores existentes funciona para usted, debe escribir su propio proveedor de servicios (implementando la interfaz de servicio) y registrarse en algún lugar (vea la publicación útil de Roman).

Si está reutilizando la implementación del proveedor existente de la interfaz de servicio, básicamente está utilizando la API de ese proveedor en particular, que incluye todos los métodos de la interfaz de servicio más algunos métodos públicos propios. Si está utilizando métodos de API de proveedor fuera del SPI, está utilizando funciones específicas del proveedor.

tapasvi
fuente
2

En el mundo de Java, las diferentes tecnologías están destinadas a ser modulares y "conectables" en un servidor de aplicaciones. Entonces hay una diferencia entre

  • el servidor de aplicaciones
    • [SPI]
  • la tecnología enchufable
    • [API]
  • la aplicación de usuario final

Dos ejemplos de tales tecnologías son JTA (el administrador de transacciones) y JCA (adaptador para JMS o base de datos). Pero hay otros.

El implementador de dicha tecnología enchufable debe implementar el SPI para que pueda enchufarse en la aplicación. servidor y proporcionar una API para ser utilizada por la aplicación de usuario final. Un ejemplo de JCA es la interfaz ManagedConnection que forma parte del SPI y la conexión que forma parte de la API del usuario final.

ewernli
fuente