Sharding-Jdbc(6)源码分析Sharding

Sharding-Jdbc 源码分析

上一篇文我们直接从sharding Jdbc的源码出发,讨论了sharding-Jdbc如何重写jdbc基础的四大基础类,现在重新从sharding-jdbc的example开始,一步一步打断点重新看一下jdbc如何建立 datasource的过程。

首先我们选用org.apache.shardingsphere.example.sharding.spring.boot.jpa这里的测试方法,修改一下本地的配置文件,使得方法可以运行
屏幕快照 2021-08-30 下午11.08.34.png

然后我们在createDatesource这里打上断点可以看到传入的参数

屏幕快照 2021-08-30 下午11.18.00.png
createDatesource方法创建了一个新的类ShardingSphereDataSource
这个类创建的第一步就是初始化MetaDataContexts类,而这个类是我们 org.apache.shardingsphere.infra 这个基础包内的一个基础类
我们这里来回顾一下infra包内的结构

shardingsphere-infra % tree -L 1

├── shardingsphere-infra-authority proxy权限配置
├── shardingsphere-infra-binder sql解析结果转换
├── shardingsphere-infra-common 重要的基本对象和工具
├── shardingsphere-infra-context 封装的上下文集合
├── shardingsphere-infra-datetime 时间服务
├── shardingsphere-infra-executor 引擎-执行引擎
├── shardingsphere-infra-merge 引擎-归并引擎
├── shardingsphere-infra-optimize 引擎-优化引擎,新加的
├── shardingsphere-infra-parser 引擎-解析引擎
├── shardingsphere-infra-rewrite 引擎-改写引擎
├── shardingsphere-infra-route   	

复制代码

singletonMap 首先处理了传入的datasouceMap参数,然后校验了XA_TRANSACTION_MANAGER_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);
}
复制代码

下文的代码中可以看到首先这个原数据上下文调用了MetaDataContextsBuilder初始化了MetaDataContexts
MetaDataContextsBuilder 中含有非常多的初始化类,我们这里先讨论build

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);
}
复制代码

初始化类初始化时候调用buildAuthentication方法,然后在方法内调用PrivilegeBuilder

屏幕快照 2021-08-31 下午2.15.01.png
PrivilegeBuilder内根据缓存和传入的user信息进行用户权限的校验和初始化,这里细节太多就不更多的讨论了
初始化完用户权限以后,开始MetaDataContextsBuilder 再初始化MetaData:


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));
}
复制代码

可以看到首先取了datasource和ruleconfig中的参数以后,使用ShardingSphereRulesBuilder 进行规则的初始化。

然后对数据库的类型进行了判断

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;
    }
}
复制代码

屏幕快照 2021-08-31 下午2.21.26.png

初始化元数据上下文以后,createDataSource会调用ShardingTransactionManagerEngine初始化事务上下文,需要配置事务以后才会实现。

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));
}
复制代码

下文再进行讨论。 Shardingsphere如何整合Atomikos对XA分布式事务的支持
如果不配置,这里就直接结束创建ShardingSphereDataSource的过程。