How to Build a Plugin‑Based Service Framework in Java Using SPI
This guide explains how to create a modular, plugin‑style service framework in Java using the Service Provider Interface (SPI), covering project structure, interface definition, implementation jars, META‑INF configuration, and a client example that loads multiple time‑service implementations at runtime.
Background: When customizing business logic, different sites require different interface implementations, so the service must be provided in a plug‑in manner.
Solution analysis:
Considered OSGi, but abandoned due to its heavyweight nature.
Considered dynamic loading via a custom class loader, but it was complex.
Adopted Java Service Provider Interface (SPI), which is lightweight and simple, and chosen as the preferred solution.
How to implement the plugin framework with Java SPI:
Create the service interface project SPI-Service that defines an abstract class or interface for all custom services.
Create the implementation project SPI-CN-Service that provides concrete implementations, packaging them as JARs with the META-INF/services file.
Create a client project SPI-Service-Client that uses ServiceLoader to discover and invoke the services. Add the JARs from steps 1 and 2 to its classpath.
Code examples:
package hxb.spi.service;
public abstract class ITimeService {
private String serviceName;
public abstract String getCurrentTime();
public String getServiceName() { return serviceName; }
public void setServiceName(String serviceName) { this.serviceName = serviceName; }
} package hxb.spi.service;
import java.text.SimpleDateFormat;
import java.util.Date;
public class CNTimeService extends ITimeService {
public CNTimeService() { super.setServiceName("CN-Time-Service"); }
@Override
public String getCurrentTime() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return getServiceName() + ":" + sdf.format(new Date());
}
} package hxb.spi.service;
import java.text.SimpleDateFormat;
import java.util.Date;
public class USTimeService extends ITimeService {
public USTimeService() { super.setServiceName("US-Time-Service"); }
@Override
public String getCurrentTime() {
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
return getServiceName() + ":" + sdf.format(new Date());
}
} // META-INF/services/hxb.spi.service.ITimeService
hxb.spi.service.CNTimeService
hxb.spi.service.USTimeService package hxb.spi.test;
import hxb.spi.service.ITimeService;
import java.util.ServiceLoader;
public class SPIClient {
public static void main(String[] args) {
ServiceLoader<ITimeService> sloader = ServiceLoader.load(ITimeService.class);
for (ITimeService iTimeService : sloader) {
System.out.println(iTimeService.getCurrentTime());
}
}
}The diagram below illustrates the project relationships.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
ITFLY8 Architecture Home
ITFLY8 Architecture Home - focused on architecture knowledge sharing and exchange, covering project management and product design. Includes large-scale distributed website architecture (high performance, high availability, caching, message queues...), design patterns, architecture patterns, big data, project management (SCRUM, PMP, Prince2), product design, and more.
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.
