概要:错误信息 Data sources cannot be empty
- shardingSphere版本
shardingshpere_version=4.1.0
sharding_jdbc_spring_namespace_version=4.1.0
compile("org.apache.shardingsphere:sharding-jdbc-spring-boot-starter:${shardingshpere_version}")
compile("org.apache.shardingsphere:sharding-jdbc-spring-namespace:${sharding_jdbc_spring_namespace_version}")
- 详细异常明细
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.sql.DataSource]: Factory method 'shardingDataSource' threw exception; nested exception is java.lang.IllegalArgumentException: Data sources cannot be empty.
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:582)
... 104 common frames omitted
Caused by: java.lang.IllegalArgumentException: Data sources cannot be empty.
at com.google.common.base.Preconditions.checkArgument(Preconditions.java:134)
at org.apache.shardingsphere.core.rule.ShardingRule.<init>(ShardingRule.java:76)
at org.apache.shardingsphere.shardingjdbc.api.ShardingDataSourceFactory.createDataSource(ShardingDataSourceFactory.java:48)
at org.apache.shardingsphere.shardingjdbc.spring.boot.SpringBootConfiguration.shardingDataSource(SpringBootConfiguration.java:103)
at org.apache.shardingsphere.shardingjdbc.spring.boot.SpringBootConfiguration$$EnhancerBySpringCGLIB$$a2810b5d.CGLIB$shardingDataSource$1(<generated>)
at org.apache.shardingsphere.shardingjdbc.spring.boot.SpringBootConfiguration$$EnhancerBySpringCGLIB$$a2810b5d$$FastClassBySpringCGLIB$$b2e37f70.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:361)
at org.apache.shardingsphere.shardingjdbc.spring.boot.SpringBootConfiguration$$EnhancerBySpringCGLIB$$a2810b5d.shardingDataSource(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
... 105 common frames omitted
- 查看源码
ShardingRule.class,发现 dataSourceNames 节点为空
public ShardingRule(final ShardingRuleConfiguration shardingRuleConfig, final Collection<String> dataSourceNames) {
Preconditions.checkArgument(null != shardingRuleConfig, "ShardingRuleConfig cannot be null.");
Preconditions.checkArgument(null != dataSourceNames && !dataSourceNames.isEmpty(), "Data sources cannot be empty.");
this.ruleConfiguration = shardingRuleConfig;
shardingDataSourceNames = new ShardingDataSourceNames(shardingRuleConfig, dataSourceNames);
tableRules = createTableRules(shardingRuleConfig);
broadcastTables = shardingRuleConfig.getBroadcastTables();
bindingTableRules = createBindingTableRules(shardingRuleConfig.getBindingTableGroups());
defaultDatabaseShardingStrategy = createDefaultShardingStrategy(shardingRuleConfig.getDefaultDatabaseShardingStrategyConfig());
defaultTableShardingStrategy = createDefaultShardingStrategy(shardingRuleConfig.getDefaultTableShardingStrategyConfig());
defaultShardingKeyGenerator = createDefaultKeyGenerator(shardingRuleConfig.getDefaultKeyGeneratorConfig());
masterSlaveRules = createMasterSlaveRules(shardingRuleConfig.getMasterSlaveRuleConfigs());
encryptRule = createEncryptRule(shardingRuleConfig.getEncryptRuleConfig());
}
反调至SpringBootConfiguration.class,发现数据源信息取自dataSourceMap
@Bean
@Conditional(ShardingRuleCondition.class)
public DataSource shardingDataSource() throws SQLException {
return ShardingDataSourceFactory.createDataSource(dataSourceMap, new ShardingRuleConfigurationYamlSwapper().swap(shardingRule), props.getProps());
}
而dataSourceMap赋值逻辑为
@Override
public final void setEnvironment(final Environment environment) {
String prefix = "spring.shardingsphere.datasource.";
for (String each : getDataSourceNames(environment, prefix)) {
try {
dataSourceMap.put(each, getDataSource(environment, prefix, each));
} catch (final ReflectiveOperationException ex) {
throw new ShardingSphereException("Can't find datasource type!", ex);
} catch (final NamingException namingEx) {
throw new ShardingSphereException("Can't find JNDI datasource!", namingEx);
}
}
}
从而可知数据源yaml配置文件因该为:spring.shardingsphere.datasource.
而自己的项目配置为sharding.dataSource
加载配置文件时没有问题,可以注入数据源和路由规则,当 @Conditional(ShardingRuleCondition.class) 生效时,会在环境中重新加载默认路径数据源,导致启动失败。
- 解决方案:
配置默认数据源路径即可