Service Provider Interface (SPI) pattern¶
The Service Provider Interface (SPI) pattern is a service-provider loading facility used to decouple service consumers from specific service implementations^[600-developer__java__black-technology__ServiceLoader.md]. It defines a standard way for an application to discover and load implementations of a programming interface dynamically at runtime, rather than compiling against them directly^[600-developer__java__black-technology__ServiceLoader.md].
Discovery Mechanism¶
The pattern relies on a conventional file location and naming structure to enable discovery^[600-developer__java__black-technology__ServiceLoader.md]. Implementations must be declared in a specific directory structure within the classpath.
- Directory: Implementation details are placed in the
META-INF/services/directory^[600-developer__java__black-technology__ServiceLoader.md]. - Configuration File: A file must be created in this directory named after the fully qualified name of the service interface (the contract)^[600-developer__java__black-technology__ServiceLoader.md].
- Content: The content of this configuration file lists the fully qualified names of the concrete classes that implement the service interface^[600-developer__java__black-technology__ServiceLoader.md].
Java Implementation¶
In the Java ecosystem, this pattern is implemented via the java.util.ServiceLoader utility class^[600-developer__java__black-technology__ServiceLoader.md].
ServiceLoader is a tool provided by the JDK that searches the classpath for configuration files matching the META-INF/services/ convention^[600-developer__java__black-technology__ServiceLoader.md] (specifically using the PREFIX constant defined as META-INF/services/^[600-developer__java__black-technology__ServiceLoader.md:115]). It uses this information to locate, load, and instantiate the provider classes defined in those files.
JDBC Use Case¶
The pattern is widely used within the Java Runtime Environment itself, such as in the JDBC DriverManager^[600-developer__java__black-technology__ServiceLoader.md].
Historically, JDBC drivers were loaded explicitly using Class.forName(), but the modern approach allows drivers to be packaged as Service Providers^[600-developer__java__black-technology__ServiceLoader.md] (lines 30-33). The DriverManager utilizes ServiceLoader.load(Driver.class) to iterate through available drivers declared in META-INF/services/java.sql.Driver^[600-developer__java__black-technology__ServiceLoader.md:38-46]. This mechanism replaced older internal methods like sun.misc.Providers, standardizing how runtimes detect vendor implementations^[600-developer__java__black-technology__ServiceLoader.md].
Sources¶
^[600-developer__java__black-technology__ServiceLoader.md]
Related Concepts¶
- [[Interface (Java)]]
- [[Factory pattern]]
- [[Dependency Injection]]