SPI is an extension mechanism that implements a service provider framework.
See a whole simple example on GitHub
The whole SPI concept is construct round the loading of new provider with the ServiceLoader.
A set of programming interfaces and classes that provide access to some specific application functionality or feature.
A service is a well-known set of interfaces and (usually abstract) classes.
The set of public interfaces and abstract classes that a service defines. The SPI defines the classes and methods available to your application.
A service provider is a specific implementation of a service. The classes in a provider typically implement the interfaces and subclass the classes defined in the service itself.
It's not an error to install more than one provider for the same service. For example, two different service providers might supply support for reading the same type of sound file. In such a case, the system arbitrarily chooses one of the providers. Users who care which provider is chosen should install only the desired one.
Service providers supply their new services in specially formatted JAR files.
The service provider is declared through a provider-configuration file located in the resource directory META-INF/services
Example with FileSystemProvider.class that is the SPI interface of NIO.
ServiceLoader<FileSystemProvider> loader = ServiceLoader.load(FileSystemProvider.class);
for (FileSystemProvider provider: loader) {
System.out.println("Provider: "+provider.class.toString()+" with scheme "+provider.getScheme());
}
ServiceLoader<FileSystemProvider> sl = ServiceLoader.load(FileSystemProvider.class, ClassLoader.getSystemClassLoader());
for (FileSystemProvider provider: sl) {
System.out.println("Provider: "+provider.class.toString()+" with scheme "+provider.getScheme());
}