Principle:Apache Shardingsphere SPI Refresher Loading
| Knowledge Sources | |
|---|---|
| Domains | Metadata_Management, DDL_Processing |
| Last Updated | 2026-02-10 00:00 GMT |
Overview
A plugin architecture should use a service provider interface (SPI) mechanism to dynamically load type-specific handlers, allowing new DDL statement types to be supported without modifying the core engine.
Description
The SPI Refresher Loading principle governs how the metadata refresh engine discovers and loads the correct refresher implementation for a given DDL statement type. Rather than using conditional branching (if/else or switch statements) to route each DDL type to its handler, the system uses Java's Service Provider Interface (SPI) pattern, extended by ShardingSphere's TypedSPI framework.
Each DDL statement type (e.g., CreateTableStatement, AlterTableStatement, DropViewStatement) maps to a specific refresher implementation through the SPI registry. The refresher interface PushDownMetaDataRefresher<T extends SQLStatement> defines a generic contract parameterized by the SQL statement type. Each concrete refresher declares its type via the getType() method, which returns the statement class it handles.
The loading mechanism has a fallback strategy: if no refresher is found for the exact statement class, the loader attempts to find one registered against the statement's superclass. This supports database-vendor-specific DDL statement subclasses that extend a common base class.
The @SingletonSPI annotation ensures that each refresher implementation is instantiated only once and reused across all refresh operations, minimizing object creation overhead.
Usage
Use this principle when:
- Designing an extensible handler registry that maps operation types to their implementations.
- Adding support for a new DDL statement type: implement the PushDownMetaDataRefresher interface, register via SPI service file, and the engine discovers it automatically.
- Understanding how ShardingSphere avoids hard-coded DDL routing logic in favor of a plugin-based architecture.
Theoretical Basis
The SPI loading follows a two-level lookup with fallback:
interface PushDownMetaDataRefresher<T extends SQLStatement> extends TypedSPI:
void refresh(persistService, database, dataSourceName, schemaName,
databaseType, sqlStatement, props)
Class<T> getType() // returns the SQL statement class this refresher handles
function findPushDownMetaDataRefresher(sqlStatementContext):
statementClass = sqlStatementContext.getSqlStatement().getClass()
// Primary lookup: exact class match
refresher = TypedSPILoader.findService(PushDownMetaDataRefresher.class, statementClass)
if refresher is present:
return refresher
// Fallback lookup: superclass match (for vendor-specific subclasses)
superClass = statementClass.getSuperclass()
return TypedSPILoader.findService(PushDownMetaDataRefresher.class, superClass)
Key design aspects:
- Type-safe dispatch: The generic parameter <T extends SQLStatement> ensures that each refresher only processes its designated statement type, with compile-time type safety.
- Singleton lifecycle: The @SingletonSPI annotation guarantees one instance per refresher type, avoiding repeated instantiation.
- Superclass fallback: Handles database-specific statement subclasses (e.g., MySQLCreateTableStatement extends CreateTableStatement) without requiring individual SPI registrations for each vendor variant.
- Decoupled registration: New refreshers are added via META-INF/services files, requiring zero changes to the engine code.
The SPI registration file follows the standard Java pattern:
# META-INF/services/org.apache.shardingsphere.mode.metadata.refresher.pushdown.PushDownMetaDataRefresher
org.apache.shardingsphere.mode.metadata.refresher.pushdown.type.table.CreateTablePushDownMetaDataRefresher
org.apache.shardingsphere.mode.metadata.refresher.pushdown.type.table.AlterTablePushDownMetaDataRefresher
org.apache.shardingsphere.mode.metadata.refresher.pushdown.type.table.DropTablePushDownMetaDataRefresher
...