java api

javax swing



¿Diferencia entre SPI y API? (9)

Desde Effective Java, 2ª 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, separándolas de las implementaciones.

Hay tres componentes esenciales de una estructura de proveedor de servicios: una interfaz de servicio, que los proveedores implementan; una API de registro de proveedor, que el sistema utiliza para registrar implementaciones, dando a los clientes acceso a ellas; y una API de acceso al servicio, que los clientes utilizan 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 crean instancias de manera reflexiva (Artículo 53). En el caso de JDBC, Connection reproduce la parte 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 servicio.

Existen numerosas variantes del patrón 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 de Adaptador [Gamma95, pág. 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(); } }

¿Cuál es la diferencia entre la Interfaz del proveedor de servicios (SPI) y la Interfaz de programación de aplicaciones (API) ?

Más específicamente, para las bibliotecas de Java, ¿qué las convierte en una API y / o SPI?


En el mundo Java, las diferentes tecnologías deben 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 dichas 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 conectable debe implementar el SPI para poder conectarse en la aplicación. Servidor y proporcione una API para ser utilizada por la aplicación de usuario final. Un ejemplo de JCA es la interfaz ManagedConnection que forma parte de la SPI y la Connection que forma parte de la API del usuario final.


Hay un aspecto que no se destaca 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 es necesaria 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 libertad para 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á creando una plataforma que otras personas usan y / o extienden y no su propia API donde tiene todo el código de cliente bajo control y, por lo tanto, puede refactorizar lo que necesite.

Vamos a mostrarlo en uno de los objetos Java Collection y Collections .

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

Collections.emptySet();

Dado que todos los clientes están "llamando" pero no "implementando" , los autores de JDK pueden agregar nuevos métodos al objeto Collections en la versión futura de JDK. Pueden estar seguros de que no puede quebrar a ningún cliente, incluso si hay miles 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 implementación de Collection (*).

Normalmente, cuando se requiere agregar un método adicional, se debe crear una nueva interfaz, por ejemplo, Collection2 que amplía 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 debe mantener la versión anterior.

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

Si algo no está claro, recomiendo consultar esta página, que explica más detalladamente lo anterior.

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


La diferencia entre API y SPI se produce cuando una API adicionalmente proporciona algunas implementaciones concretas. En ese caso, el proveedor de servicios debe 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 utilizará internamente interfaces SPI (utilizando NamingManager) para implementaciones específicas del proveedor.

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


La interfaz del proveedor de servicios es la interfaz de servicios 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 (consulte la publicación útil de Roman).

Si está reutilizando la implementación de la interfaz de servicio del proveedor existente, básicamente está utilizando la API de ese proveedor en particular, que incluye todos los métodos de 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 características específicas del proveedor.


Preguntas frecuentes de NetBeans: ¿Qué es un SPI? ¿En qué se diferencia de una API?

API es un término general, un acrónimo de Application Programming Interface (Interfaz de programación de aplicaciones), significa algo (en Java, generalmente algunas clases de Java) que un software expone, lo que permite que otro software se comunique con él.

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 generalmente 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 llama si está escribiendo un cliente de correo o si desea leer un buzón
  • El lado SPI si está proporcionando un controlador de protocolo de conexión para permitir que JavaMail se comunique 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 de 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, lo que permite 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 los archivos (el lado de la API) no tiene por qué preocuparse si existe un sistema de control de versiones, o lo que es.


Supongo que las ranuras SPI en un sistema más grande implementan ciertas características de una API y luego se registran a sí mismas como disponibles a través de los 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.


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 de un software o una plataforma.

Normalmente, la API es un destino 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 modificadas / eliminadas a menos que haya una comunicación apropiada, ya que es una degradación completa de las expectativas del cliente

SPI en la otra parte 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. programmatic)

-> 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 implementaciones existentes

Para obtener más información, haga clic aquí: Interfaz del proveedor de servicios


  • La API es la descripción de las clases / interfaces / métodos / ... que usted llama y usa para lograr un objetivo, y
  • El SPI es la descripción de las clases / interfaces / métodos / ... que 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 son independientes. Por ejemplo, en JDBC, la clase Driver es parte de SPI: si simplemente desea usar JDBC, no necesita usarlo directamente, pero todos los que implementan un controlador JDBC deben implementar esa clase.

Sin embargo, a veces se superponen. La interfaz de Connection es SPI y API: la usa de forma rutinaria cuando usa un controlador JDBC y el desarrollador del controlador JDBC debe implementarla.