Principle:Apache Dolphinscheduler SPI Plugin Registration
| Knowledge Sources | |
|---|---|
| Domains | Plugin_Architecture, Service_Discovery |
| Last Updated | 2026-02-10 00:00 GMT |
Overview
A service discovery mechanism using Java SPI (ServiceLoader) with Google AutoService for compile-time registration file generation, enabling runtime plugin discovery without compile-time coupling.
Description
The SPI Plugin Registration principle leverages Javas ServiceLoader mechanism to discover and load datasource plugins at runtime. Each plugin class is annotated with @AutoService which generates the META-INF/services/ registration file during compilation. At startup, DataSourceProcessorManager loads all DataSourceProcessor implementations and DataSourcePluginManager loads all DataSourceChannelFactory implementations using ServiceLoader / PrioritySPIFactory.
This pattern eliminates the need for manual plugin registration or configuration files, enabling a clean plug-and-play architecture where adding a new database plugin requires only placing its JAR on the classpath.
Usage
Use this pattern to register your datasource plugin. Annotate the processor class with @AutoService(DataSourceProcessor.class) and the channel factory with @AutoService(DataSourceChannelFactory.class). The SPI managers will automatically discover and register your plugin at startup.
Theoretical Basis
The SPI Plugin Registration implements the Service Locator Pattern with compile-time safety:
- Service Interface: DataSourceProcessor and DataSourceChannelFactory define the contracts
- Service Providers: Each plugin implements the interfaces
- Service Registry: META-INF/services/ files (auto-generated by @AutoService)
- Service Locator: ServiceLoader discovers and instantiates providers at runtime
// Registration flow
@AutoService(DataSourceProcessor.class) // Compile-time: generates META-INF/services
class MySQLProcessor extends AbstractDataSourceProcessor { ... }
// Discovery flow (at runtime)
ServiceLoader<DataSourceProcessor> loader = ServiceLoader.load(DataSourceProcessor.class);
for (DataSourceProcessor processor : loader) {
registry.put(processor.getDbType().name(), processor);
}