问题描述
最近公司搭建springboot项目 由于之前都是使用的spring项目 对于boot的理解还是不深 通过找一些文档搭建好了shardingJdbc分库分表的配置 使用了properties方式 参考官网配置如下
我们项目数据源使用了HikariCP 由于要对于数据连接池进行配置 方便出现问题调优 网上翻遍了配置整合 都是只有springboot初始的Hikari配置 与sharding整合的配置没有涉及到
传统springboot单数据源数据源整合配置
由于使用了分库分表 数据源前缀不同 肯定不能使用之前的配置方式 自己依样画葫芦写了点配置 发现竟然生效了
sharding.jdbc.datasource.ds0.pool-name=Retail_HikariCP0
sharding.jdbc.datasource.ds0.maximum-pool-size = 20
控制台出现了新的cpName!! 这就让我燃起了希望 同时又找到了https://www.cnblogs.com/aut-lory/p/10789573.html 这篇博主的文章 让我下定决心动手debug源码 查看我的配置是否生效 以及到底什么样的前缀配置才会被sharding发现并且注入
问题解决
数据源是spring初始化配置时加载的 很容易联想到spring-shardingjdbc-starter的自动配置 找到starter的factories文件
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
io.shardingsphere.shardingjdbc.spring.boot.SpringBootConfiguration
找到了自动配置类的路径 SpringBootConfiguration
@Configuration
@EnableConfigurationProperties({SpringBootShardingRuleConfigurationProperties.class, SpringBootMasterSlaveRuleConfigurationProperties.class})
public class SpringBootConfiguration implements EnvironmentAware {
@Autowired
private SpringBootShardingRuleConfigurationProperties shardingProperties;
@Autowired
private SpringBootMasterSlaveRuleConfigurationProperties masterSlaveProperties;
private final Map<String, DataSource> dataSourceMap = new LinkedHashMap<>();
/**
* Get data source bean.
*
* @return data source bean
* @throws SQLException SQL exception
*/
@Bean
public DataSource dataSource() throws SQLException {
return null == masterSlaveProperties.getMasterDataSourceName()
? ShardingDataSourceFactory.createDataSource(dataSourceMap, shardingProperties.getShardingRuleConfiguration(), shardingProperties.getConfigMap(), shardingProperties.getProps())
: MasterSlaveDataSourceFactory.createDataSource(
dataSourceMap, masterSlaveProperties.getMasterSlaveRuleConfiguration(), masterSlaveProperties.getConfigMap(), masterSlaveProperties.getProps());
}
@Override
public final void setEnvironment(final Environment environment) {
setDataSourceMap(environment);
}
@SuppressWarnings("unchecked")
private void setDataSourceMap(final Environment environment) {
String prefix = "sharding.jdbc.datasource.";
String dataSources = environment.getProperty(prefix + "names");
for (String each : dataSources.split(",")) {
try {
Map<String, Object> dataSourceProps = PropertyUtil.handle(environment, prefix + each, Map.class);
Preconditions.checkState(!dataSourceProps.isEmpty(), "Wrong datasource properties!");
DataSource dataSource = DataSourceUtil.getDataSource(dataSourceProps.get("type").toString(), dataSourceProps);
dataSourceMap.put(each, dataSource);
} catch (final ReflectiveOperationException ex) {
throw new ShardingException("Can't find datasource type!", ex);
}
}
}
}
配置类方法很少很容易读懂
当你看到setDataSourceMap方法底下的String prefix = "sharding.jdbc.datasource."; 就应该有灵敏的嗅觉 这里就是解析配置数据源配置文件把他塞到map里 我们就找到了debug的入口
如我们所愿果然debug到了
我们注意方法的参数final Environment environment 我们通过键入environment.getProperty的方法再通过debug界面观察他的属性
可以发现他就是解析了各种配置文件的内容 里面的source字段存放着所有配置文件的key-value 很容易就可以找到我们之前配置的多数据源的配置内容
for (String each : dataSources.split(",")) {
try {
Map<String, Object> dataSourceProps = PropertyUtil.handle(environment, prefix + each, Map.class);
Preconditions.checkState(!dataSourceProps.isEmpty(), "Wrong datasource properties!");
DataSource dataSource = DataSourceUtil.getDataSource(dataSourceProps.get("type").toString(), dataSourceProps);
dataSourceMap.put(each, dataSource);
} catch (final ReflectiveOperationException ex) {
throw new ShardingException("Can't find datasource type!", ex);
}
}
上面的代码则是对我们之前配置的多数据源依次解析配置 注意其中的DataSourceUtil.getDataSource方法
太爽了 直接找到了我们配置的ds0数据的配置 看到我们新加的cpname和max连接数
for (Entry<String, Object> entry : dataSourceProperties.entrySet()) {
callSetterMethod(result, getSetterMethodName(entry.getKey()), null == entry.getValue() ? null : entry.getValue().toString());
}
这段for循环则是通过反射判断dataSourceProps里面的内容 按照类型反射使用set方法 存到datasource对象中去。
DataSource result = (DataSource) Class.forName(dataSourceClassName).newInstance();
datasource对象的类型则是第一行代码 反射获取的具体类型,而且里面拥有的属性 在接下来都会一一对应dataSourceProps的key 如果存在再set进数据源对象里进行配置 到这里其实肯定有疑问 dataSourceProps 是怎么解析的呢 让我们回到最初的自动配置的那个循环上
键入之后找到了具体的执行方法
最后返回一个配置文件解析的map
最终结论
如何设置连接池的附加配置 则只需要在sharding.jdbc.datasource.(数据源名) 后直接加上属性内容 如hikari连接池 则类似 sharding.jdbc.datasource.ds0.maximum-pool-size = 20 无需像springboot默认配置 如spring.datasource.hikari.maximum-pool-size=20 加上一个hikari 前缀 (前提是整合的shardingJdbc) 结论十分简单啊 第一次分析源码去解决问题 还是很有成就感的
来源:oschina
链接:https://my.oschina.net/u/4054187/blog/3166596