Principle:Apache Shardingsphere SPI Builder Loading
| Knowledge Sources | |
|---|---|
| Domains | Cluster_Mode, Distributed_Coordination |
| Last Updated | 2026-02-10 00:00 GMT |
Overview
Using the Service Provider Interface (SPI) mechanism to dynamically load and invoke the correct context manager builder enables mode-agnostic bootstrap of a distributed database system.
Description
SPI Builder Loading is the principle of decoupling the bootstrap entry point from any specific mode implementation (Standalone, Cluster, or future modes) by relying on Java's SPI mechanism to discover and instantiate the appropriate ContextManagerBuilder at runtime.
In Apache ShardingSphere, the ContextManagerBuilder interface extends TypedSPI and is annotated with @SingletonSPI. Each mode provides its own implementation:
- StandaloneContextManagerBuilder -- registered with type
"Standalone" - ClusterContextManagerBuilder -- registered with type
"Cluster"
The bootstrap code never references these concrete classes directly. Instead, it extracts the mode type string from the ModeConfiguration (e.g., "Cluster") and uses TypedSPILoader to locate the matching builder. This pattern provides:
- Extensibility: New modes can be added by implementing ContextManagerBuilder and registering it via
META-INF/serviceswithout modifying any existing code. - Loose Coupling: The entry point depends only on the ContextManagerBuilder interface, not on any concrete builder class.
- Configuration-Driven Selection: The mode type string in the user's YAML configuration directly determines which builder is loaded at runtime.
- Singleton Guarantee: The
@SingletonSPIannotation ensures that each builder type is instantiated only once per classloader, avoiding redundant initialization.
The ClusterContextManagerBuilder.build() method orchestrates the entire cluster-mode initialization sequence: it validates and retrieves the cluster repository configuration, initializes the distributed coordination repository, creates the compute node instance context, builds the metadata contexts, registers the node online, and sets up event listeners.
Usage
Use this principle whenever the ShardingSphere bootstrap must select a mode-specific initialization strategy. The entry point (JDBC ShardingSphereDriver or Proxy Bootstrap) reads the mode type from configuration and delegates to the SPI-loaded builder. The builder's build() method returns a fully initialized ContextManager ready for query processing.
Theoretical Basis
The SPI Builder Loading principle combines several design patterns:
1. Strategy Pattern via SPI
The ContextManagerBuilder interface defines a strategy for building a context manager. Concrete implementations provide mode-specific strategies. The SPI mechanism acts as a factory that selects the strategy based on a type key:
FUNCTION bootstrapContextManager(param, eventBusContext):
modeType = param.getModeConfiguration().getType()
builder = TypedSPILoader.getService(ContextManagerBuilder.class, modeType)
RETURN builder.build(param, eventBusContext)
2. Cluster Build Orchestration
When the loaded builder is the Cluster implementation, the build() method performs a specific initialization sequence:
FUNCTION ClusterContextManagerBuilder.build(param, eventBusContext):
modeConfig = param.getModeConfiguration()
repositoryConfig = modeConfig.getRepository() -- cast to ClusterPersistRepositoryConfiguration
// Step 1: Create compute node instance context
instanceContext = new ComputeNodeInstanceContext(instance, modeConfig, eventBusContext)
// Step 2: Initialize cluster persist repository via SPI
repository = loadAndInitRepository(repositoryConfig, instanceContext)
// Step 3: Initialize worker ID generator
instanceContext.init(new ClusterWorkerIdGenerator(repository, instanceId))
// Step 4: Create metadata contexts from persisted or local configuration
metaDataContexts = MetaDataContextsFactory.create(param)
// Step 5: Assemble the context manager
contextManager = new ContextManager(metaDataContexts, instanceContext, exclusiveEngine, repository)
// Step 6: Register online and set up event listeners
registerOnline(instanceContext, param, contextManager)
registerDeliverEventSubscribers(repository)
RETURN contextManager
3. Precondition Validation
The cluster builder validates that a non-null ClusterPersistRepositoryConfiguration is present before proceeding. This fail-fast approach prevents obscure errors later in the initialization chain:
FUNCTION getClusterPersistRepository(config, instanceContext):
PRECONDITION: config IS NOT NULL
ELSE THROW MissingRequiredClusterRepositoryConfigurationException
repository = TypedSPILoader.getService(ClusterPersistRepository.class, config.getType())
repository.init(config, instanceContext)
RETURN repository
4. Open/Closed Principle
The system is open for extension (new mode builders can be added) but closed for modification (existing bootstrap code does not change when new modes are introduced).