Sharding-Jdbc source code analysis
In sharding Jdbc, you can rewrite the four basic classes of the Jdbc base by using sharding-JDBC as an example. Take a step-by-step look at how JDBC builds a datasource.
First we chooseorg.apache.shardingsphere.example.sharding.spring.boot.jpa
To test the method, modify the local configuration file to make it work
We then put a breakpoint on createDatesource to see the parameters passed in
The createDatesource method creates a new classShardingSphereDataSource
The first step in creating this class is initializationMetaDataContexts
Class, and that class is us org.apache.shardingsphere.infra
One of the base classes in the base package let’s review the structures in the infra package here
Shardingsphere-infra % tree-L 1 ├─ ShardingSphere-Infra - Authority Proxy ├─ ShardingSphere-Infra - Binder SQL Parsing Result ├─ ShardingSphere-Infra-Common Important Basic Objects and Tools ├─ ShardingSphere-Infra-Context Set ├─ ShardingSphere-Infra-DateTime Time Services ├─ ShardingSphere-Infra - Executor Engine - Execution Engine ├─ ShardingSphere-Infra merge Engine - Merge Engine ├─ ShardingSphere-Infra - Optimize Engine - Optimization engine, New ├─ ShardingSphere Infra - Parser Engine └ ─ ShardingSphere Infra - Rewrite Engine ├─ ShardingSphere Infra - RouteCopy the code
SingletonMap first processes the incoming datasouceMap parameter and then validates XA_TRANSACTION_MANAGER_TYPE (flexible transaction type).
public ShardingSphereDataSource(final Map<String, DataSource> dataSourceMap, final Collection<RuleConfiguration> configurations, final Properties props) throws SQLException {
metaDataContexts = new MetaDataContextsBuilder(
Collections.singletonMap(DefaultSchema.LOGIC_NAME, dataSourceMap), Collections.singletonMap(DefaultSchema.LOGIC_NAME, configurations), props).build();
String xaTransactionMangerType = metaDataContexts.getProps().getValue(ConfigurationPropertyKey.XA_TRANSACTION_MANAGER_TYPE);
transactionContexts = createTransactionContexts(metaDataContexts.getDefaultMetaData().getResource().getDatabaseType(), dataSourceMap, xaTransactionMangerType);
}
Copy the code
MetaDataContextsBuilder contains a large number of initialization classes, so we will discuss build first
public StandardMetaDataContexts build() throws SQLException {
Map<String, ShardingSphereMetaData> mataDataMap = new HashMap<>(ruleConfigs.size(), 1);
Authentication authentication = buildAuthentication(users, mataDataMap);
for (String each : ruleConfigs.keySet()) {
mataDataMap.put(each, buildMetaData(each));
}
return new StandardMetaDataContexts(mataDataMap, executorEngine, authentication, props);
}
Copy the code
The initializer class initializes by calling the buildAuthentication method and then calling PrivilegeBuilder within the method
PrivilegeBuilder
MetaDataContextsBuilder (); MetaDataContextsBuilder (); MetaDataContextsBuilder ();
private ShardingSphereMetaData buildMetaData(final String schemaName) throws SQLException {
Map<String, DataSource> dataSourceMap = dataSources.get(schemaName);
Collection<RuleConfiguration> ruleConfigs = this.ruleConfigs.get(schemaName);
DatabaseType databaseType = getDatabaseType(dataSourceMap);
Collection<ShardingSphereRule> rules = ShardingSphereRulesBuilder.build(ruleConfigs, databaseType, dataSourceMap, schemaName);
ShardingSphereRuleMetaData ruleMetaData = new ShardingSphereRuleMetaData(ruleConfigs, rules);
return new ShardingSphereMetaData(schemaName, buildResource(databaseType, dataSourceMap), ruleMetaData, buildSchema(schemaName, databaseType, dataSourceMap, rules));
}
Copy the code
Can see the first took a datasource and ruleconfig parameters, using ShardingSphereRulesBuilder for initialization of the rules.
Then the type of database is judged
private DatabaseType getDatabaseType(final Map<String, DataSource> dataSourceMap) { DatabaseType result = null; for (DataSource each : dataSourceMap.values()) { DatabaseType databaseType = getDatabaseType(each); Preconditions.checkState(null == result || result == databaseType, String.format("Database type inconsistent with '%s' and '%s'", result, databaseType)); result = databaseType; } return null == result ? DatabaseTypeRegistry.getDefaultDatabaseType() : result; } private DatabaseType getDatabaseType(final DataSource dataSource) { try (Connection connection = dataSource.getConnection()) { return DatabaseTypeRegistry.getDatabaseTypeByURL(connection.getMetaData().getURL()); } catch (final SQLException ex) { return null; }}Copy the code
After initial metadata context, createDataSource invokes ShardingTransactionManagerEngine initialization transaction context, need to configure the transaction will happen in the future.
private TransactionContexts createTransactionContexts(final DatabaseType databaseType, final Map<String, DataSource> dataSourceMap, final String xaTransactionMangerType) {
ShardingTransactionManagerEngine engine = new ShardingTransactionManagerEngine();
engine.init(databaseType, dataSourceMap, xaTransactionMangerType);
return new StandardTransactionContexts(Collections.singletonMap(DefaultSchema.LOGIC_NAME, engine));
}
Copy the code
More on that below. How Shardingsphere integrates Atomikos’ support for XA distributed transactions If not configured, this ends the process of creating a ShardingSphereDataSource directly.