学习一下springboot是如何整合sharding-jdbc的。
添加依赖以后
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.1.1</version>
</dependency>
由于springboot自动装配可知会自动加载这个类
org.apache.shardingsphere.shardingjdbc.spring.boot.SpringBootConfiguration
SpringBootConfiguration实现了接口EnvironmentAware 其主要属性如下:
private final SpringBootShardingRuleConfigurationProperties shardingRule;
private final SpringBootMasterSlaveRuleConfigurationProperties masterSlaveRule;
private final SpringBootEncryptRuleConfigurationProperties encryptRule;
private final SpringBootShadowRuleConfigurationProperties shadowRule;
private final SpringBootPropertiesConfigurationProperties props;
private final Map<String, DataSource> dataSourceMap = new LinkedHashMap();
private final String jndiName = "jndi-name";
主要用来读取各种配置项,结合配置文件:
spring.shardingsphere.datasource.names=wim-user,wim-order
spring.shardingsphere.datasource.wim-user.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.wim-user.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.wim-user.url=jdbc:mysql://127.0.0.1:3306/wim-user?serverTimezone=UTC&useSSL=false
spring.shardingsphere.datasource.wim-user.username=root
spring.shardingsphere.datasource.wim-user.password=123456
spring.shardingsphere.datasource.wim-order.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.wim-order.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.wim-order.url=jdbc:mysql://127.0.0.1:3306/wim-order?serverTimezone=UTC&useSSL=false
spring.shardingsphere.datasource.wim-order.username=root
spring.shardingsphere.datasource.wim-order.password=123456
spring.shardingsphere.sharding.tables.user_t.actual-data-nodes=wim-user.user_t
spring.shardingsphere.sharding.tables.log_t.actual-data-nodes=wim-user.log_t
#spring.shardingsphere.sharding.tables.user_t.table-strategy.inline.sharding-column=user_id
#spring.shardingsphere.sharding.tables.user_t.table-strategy.inline.algorithm-expression=user_t
#
#spring.shardingsphere.sharding.tables.log_t.table-strategy.inline.sharding-column=user_id
#spring.shardingsphere.sharding.tables.log_t.table-strategy.inline.algorithm-expression=log_t
spring.shardingsphere.sharding.default-data-source-name=wim-order
spring.shardingsphere.props.sql.show=true
spring.shardingsphere.datasource前缀会自动解析成数据源 dataSourceMap
spring.shardingsphere.sharding前缀会自动解析成数据库分片配置 shardingRule
spring.shardingsphere.props前缀会解析成属性配置 props
其余几个配置
masterSlaveRule 读写分离配置
encryptRule加密配置
shadowRule影子表配置
在setEnvironment方法中实现数据源的配置项加载和初始化
public final void setEnvironment(Environment environment) {
String prefix = "spring.shardingsphere.datasource.";
Iterator var3 = this.getDataSourceNames(environment, prefix).iterator();
while(var3.hasNext()) {
String each = (String)var3.next();
try {
this.dataSourceMap.put(each, this.getDataSource(environment, prefix, each));
} catch (ReflectiveOperationException var6) {
throw new ShardingSphereException("Can't find datasource type!", var6);
} catch (NamingException var7) {
throw new ShardingSphereException("Can't find JNDI datasource!", var7);
}
}
}
此时dataSourceMap中含有所有配置的数据源配置项,容器启动时具体使用何种数据源由相应配置项来决定
public final class ShardingRuleCondition extends SpringBootCondition {
public ShardingRuleCondition() {
}
public ConditionOutcome getMatchOutcome(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
boolean isMasterSlaveRule = (new MasterSlaveRuleCondition()).getMatchOutcome(conditionContext, annotatedTypeMetadata).isMatch();
boolean isEncryptRule = (new EncryptRuleCondition()).getMatchOutcome(conditionContext, annotatedTypeMetadata).isMatch();
boolean isShadow = (new ShadowRuleCondition()).getMatchOutcome(conditionContext, annotatedTypeMetadata).isMatch();
return !isMasterSlaveRule && !isEncryptRule && !isShadow ? ConditionOutcome.match() : ConditionOutcome.noMatch("Have found master-slave or encrypt rule in environment");
}
}
如果有spring.shardingsphere.masterslave.name加载主从数据源模式
如果有spring.shardingsphere.encrypt.encryptors加载加密数据源模式
如果有spring.shardingsphere.shadow加载主从数据源模式其他则加载影子库数据源模式
由于我们只配置了分片规则,因此会初始化shardingDataSource
@Bean
@Conditional({ShardingRuleCondition.class})
public DataSource shardingDataSource() throws SQLException {
return ShardingDataSourceFactory.createDataSource(this.dataSourceMap, (new ShardingRuleConfigurationYamlSwapper()).swap(this.shardingRule), this.props.getProps());
}
因此容器中最终的数据源对象为ShardingDataSource
public static DataSource createDataSource(Map<String, DataSource> dataSourceMap, ShardingRuleConfiguration shardingRuleConfig, Properties props) throws SQLException {
return new ShardingDataSource(dataSourceMap, new ShardingRule(shardingRuleConfig, dataSourceMap.keySet()), props);
}
ShardingDataSource数据源中通过ShardingRuntimeContext对象来实现上下文对象保存和传递以及功能增强
private final ShardingRuntimeContext runtimeContext;
public ShardingDataSource(Map<String, DataSource> dataSourceMap, ShardingRule shardingRule, Properties props) throws SQLException {
super(dataSourceMap);
this.checkDataSourceType(dataSourceMap);
this.runtimeContext = new ShardingRuntimeContext(dataSourceMap, shardingRule, props, this.getDatabaseType());
}
ShardingRuntimeContext中主要包括 缓存的数据源元数据信息以及事务管理器
private final CachedDatabaseMetaData cachedDatabaseMetaData;
private final ShardingTransactionManagerEngine shardingTransactionManagerEngine;
public ShardingRuntimeContext(Map<String, DataSource> dataSourceMap, ShardingRule shardingRule, Properties props, DatabaseType databaseType) throws SQLException {
super(dataSourceMap, shardingRule, props, databaseType);
this.cachedDatabaseMetaData = this.createCachedDatabaseMetaData(dataSourceMap);
this.shardingTransactionManagerEngine = new ShardingTransactionManagerEngine();
this.shardingTransactionManagerEngine.init(databaseType, dataSourceMap);
}
应用启动后加载的数据库元数据相关信息