Plugin Architecture in Java: SPI, ServiceLoader, and Spring Boot Implementations
This article explains the benefits and common practices of plugin‑based development in Java, covering module decoupling, extensibility, third‑party integration, and detailed implementations using Java SPI, custom configuration loading, and Spring Boot's spring.factories mechanism with practical code examples.
Plugin‑based development is widely used in many programming languages and frameworks such as Jenkins, Rancher, IDEA, and VSCode, providing hot‑plug capabilities that greatly improve system extensibility, scalability, and overall value.
Typical Java plugin implementations include the SPI mechanism, convention‑based configuration with reflection, Spring Boot's Factories mechanism, Java agents, built‑in Spring extension points, and third‑party plugin libraries.
ServiceLoader (Java SPI) example: define a common interface
public interface MessagePlugin { String sendMsg(Map msgMap); }and two implementations:
public class AliyunMsg implements MessagePlugin { @Override public String sendMsg(Map msgMap) { System.out.println("aliyun sendMsg"); return "aliyun sendMsg"; } } public class TencentMsg implements MessagePlugin { @Override public String sendMsg(Map msgMap) { System.out.println("tencent sendMsg"); return "tencent sendMsg"; } }Register the implementations in META-INF/services/com.congge.plugins.spi.MessagePlugin and load them with:
ServiceLoader<MessagePlugin> loader = ServiceLoader.load(MessagePlugin.class); for (MessagePlugin p : loader) { p.sendMsg(context); }Custom configuration loading: a YAML/Properties file lists implementation class names, e.g.
impl:
name: com.congge.plugins.spi.MessagePlugin
clazz:
- com.congge.plugins.impl.TencentMsg
- com.congge.plugins.impl.AliyunMsgThe ServiceLoaderUtils class reads the file, creates a URLClassLoader for each JAR in a designated directory, and uses reflection to invoke sendMsg on the loaded classes.
Spring Boot plugin via spring.factories : define an interface
public interface SmsPlugin { void sendMessage(String message); }and two implementations BizSmsImpl and SystemSmsImpl. Add a META-INF/spring.factories entry:
com.congge.plugin.spi.SmsPlugin=\
com.congge.plugin.impl.SystemSmsImpl,\
com.congge.plugin.impl.BizSmsImplLoad all implementations with
List<SmsPlugin> plugins = SpringFactoriesLoader.loadFactories(SmsPlugin.class, null); for (SmsPlugin p : plugins) { p.sendMessage(msg); }and expose a controller endpoint to trigger the plugins.
The article also presents a complete case study that combines these techniques: a multi‑module Maven project (biz‑pp, bitpt, miz‑pt) where MessagePlugin is defined in a core module, concrete SMS providers implement it, and a PluginFactory selects the appropriate implementation based on configuration. Controllers, services, and Maven dependencies are shown to illustrate how to integrate the plugin system into a real Spring Boot application.
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.
Sohu Tech Products
A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.
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.
