How to Implement Java SPI with Maven Multi‑Module Projects and Spring Boot
This guide explains Java's Service Provider Interface (SPI) mechanism, compares it with traditional APIs, and walks through building a multi‑module Maven project that defines an SPI, provides a default implementation, creates an external plugin jar, loads it at runtime with a custom class loader, and integrates the service into a Spring Boot application.
Java SPI (Service Provider Interface) is a discovery mechanism that lets developers define an interface and load multiple implementations at runtime without changing business code. Implementations are placed under META-INF/services with a file named after the interface's fully‑qualified name containing the implementation class names.
Key Uses of Java SPI
Allows service providers to extend frameworks without modifying the core code.
Supports dynamic insertion or replacement of components, encouraging loose coupling.
Enables third‑party libraries to plug into core systems, increasing flexibility.
SPI vs. API
Definition: APIs are written by developers for external use, while SPI interfaces are defined by frameworks for third‑party implementations.
Invocation: APIs are called directly; SPI implementations are selected via configuration files and loaded automatically.
Flexibility: API implementations are fixed at compile time; SPI implementations can be swapped at runtime.
Dependency: Applications depend on the API library; frameworks depend on the plugin implementations.
Purpose: APIs expose functionality; SPI provides a plug‑in architecture for extensibility.
Project Structure
sa-auth (parent pom)
├─ sa-auth-bus // business module
├─ sa-auth-plugin // defines the SPI interface
└─ sa-auth-plugin-ldap // external plugin implementing the SPIStep‑by‑Step Implementation
Create the parent Maven project sa-auth with packaging pom and define common properties.
In sa-auth-plugin, define the SPI interface AuthPluginService with methods boolean login(String userName, String password) and String getAuthServiceName(). Add a
META-INF/services/com.vijay.csauthplugin.service.AuthPluginServicefile containing the implementation class name.
Implement a default provider DefaultProviderImpl in sa-auth-bus and register it via its own META-INF/services file.
Create an external plugin module sa-auth-plugin-ldap that implements AuthPluginService (class LdapProviderImpl) and package it as a jar.
Write a custom class loader PluginClassLoader extending URLClassLoader and a utility ExternalJarLoader.loadExternalJars(String path) to load all jar files from a directory and set the thread context class loader.
In the Spring Boot application ( CsAuthBusApplication), call ExternalJarLoader.loadExternalJars("/path/to/plugin") before starting the application.
Create PluginProvider that uses ServiceLoader to obtain the first AuthPluginService implementation, preferring the external one and falling back to the default.
Configure a Spring bean in PluginConfig that returns PluginProvider.getAuthPluginService(), making the SPI implementation injectable.
Add a REST controller TestController that injects AuthPluginService and exposes an endpoint /test returning the provider name and login result.
Running the Example
Start the Spring Boot application, first with only the default provider – the /test endpoint returns DefaultProvider. Then place the sa-auth-plugin-ldap.jar into the external plugin directory, restart the app, and the endpoint now returns LdapProvider, demonstrating dynamic discovery.
This example shows how to build a modular Java project, define an SPI, create pluggable implementations, load them at runtime, and integrate the service into a Spring Boot application.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
