shardingjdbc4.x初始化数据源过程

shardingjdbc4.x初始化数据源过程

前言

看过好几遍了老是忘记,idea点击配置时总是跳转到DataSourceUtil中引起误解。所以我这次要把他记录下来。


使用shardingjdbc4.x配置数据源时,一般我们是这个配置的。那他背后是如何将数据源创建出来的呢,下面请看源码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14

spring.shardingsphere.datasource.names=ds0,ds1

spring.shardingsphere.datasource.ds0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds0.driver-class-name=software.aws.rds.jdbc.mysql.Driver
spring.shardingsphere.datasource.ds0.jdbc-url=jdbc:mysql:127.0.0.1:3306/xxx?useUnicode=true&characterEncoding=utf-8&transformedBitIsBoolean=true&allowMultiQueries=true&useSSL=false
spring.shardingsphere.datasource.ds0.username=username
spring.shardingsphere.datasource.ds0.password=password

spring.shardingsphere.datasource.ds1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds1.driver-class-name=software.aws.rds.jdbc.mysql.Driver
spring.shardingsphere.datasource.ds1.jdbc-url=jdbc:mysql:127.0.0.1:3306/xxx?useUnicode=true&characterEncoding=utf-8&transformedBitIsBoolean=true&allowMultiQueries=true&useSSL=false
spring.shardingsphere.datasource.ds1.username=username
spring.shardingsphere.datasource.ds1.password=password

这里我们使用Hikari连接池初始化了两个名称为ds0,ds1的数据源。下面解释下他背后是怎么配置数据源的

首先在:org.apache.shardingsphere.shardingjdbc.spring.boot.SpringBootConfiguration 类中有下面这样一段代码

他会从环境中查找 spring.shardingsphere.datasource.names前缀的配置,也就是我们上面的配置的两个数据源名字,逗号分隔
然后依次将每个数据源名称前面拼接上 spring.shardingsphere.datasource.前缀开始查找配置,并使用 DataSourceUtil工具类将数据源反射创建出来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
@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);
}
}
}

private List<String> getDataSourceNames(final Environment environment, final String prefix) {
StandardEnvironment standardEnv = (StandardEnvironment) environment;
standardEnv.setIgnoreUnresolvableNestedPlaceholders(true);
return null == standardEnv.getProperty(prefix + "name")
? new InlineExpressionParser(standardEnv.getProperty(prefix + "names")).splitAndEvaluate() : Collections.singletonList(standardEnv.getProperty(prefix + "name"));
}

@SuppressWarnings("unchecked")
private DataSource getDataSource(final Environment environment, final String prefix, final String dataSourceName) throws ReflectiveOperationException, NamingException {
Map<String, Object> dataSourceProps = PropertyUtil.handle(environment, prefix + dataSourceName.trim(), Map.class);
Preconditions.checkState(!dataSourceProps.isEmpty(), "Wrong datasource properties!");
if (dataSourceProps.containsKey(jndiName)) {
return getJndiDataSource(dataSourceProps.get(jndiName).toString());
}
DataSource result = DataSourceUtil.getDataSource(dataSourceProps.get("type").toString(), dataSourceProps);
DataSourcePropertiesSetterHolder.getDataSourcePropertiesSetterByType(dataSourceProps.get("type").toString()).ifPresent(
dataSourcePropertiesSetter -> dataSourcePropertiesSetter.propertiesSet(environment, prefix, dataSourceName, result));
return result;
}



DataSourceUtil根据指定的dataSourceClassName反射创建数据源,在赋值属性时,会根据属性名查找set方法,并对一些基本类型做转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57


@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class DataSourceUtil {

private static final String SET_METHOD_PREFIX = "set";

private static final Collection<Class<?>> GENERAL_CLASS_TYPE;

static {
GENERAL_CLASS_TYPE = Sets.newHashSet(boolean.class, Boolean.class, int.class, Integer.class, long.class, Long.class, String.class, Collection.class);
}

/**
* Get data source.
*
* @param dataSourceClassName data source class name
* @param dataSourceProperties data source properties
* @return data source instance
* @throws ReflectiveOperationException reflective operation exception
*/
public static DataSource getDataSource(final String dataSourceClassName, final Map<String, Object> dataSourceProperties) throws ReflectiveOperationException {
DataSource result = (DataSource) Class.forName(dataSourceClassName).newInstance();
for (Entry<String, Object> entry : dataSourceProperties.entrySet()) {
callSetterMethod(result, getSetterMethodName(entry.getKey()), null == entry.getValue() ? null : entry.getValue().toString());
}
return result;
}

private static String getSetterMethodName(final String propertyName) {
if (propertyName.contains("-")) {
return CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL, SET_METHOD_PREFIX + "-" + propertyName);
}
return SET_METHOD_PREFIX + String.valueOf(propertyName.charAt(0)).toUpperCase() + propertyName.substring(1);
}

private static void callSetterMethod(final DataSource dataSource, final String methodName, final String setterValue) {
for (Class<?> each : GENERAL_CLASS_TYPE) {
try {
Method method = dataSource.getClass().getMethod(methodName, each);
if (boolean.class == each || Boolean.class == each) {
method.invoke(dataSource, Boolean.valueOf(setterValue));
} else if (int.class == each || Integer.class == each) {
method.invoke(dataSource, Integer.parseInt(setterValue));
} else if (long.class == each || Long.class == each) {
method.invoke(dataSource, Long.parseLong(setterValue));
} else if (Collection.class == each) {
method.invoke(dataSource, Arrays.asList(setterValue.split(",")));
} else {
method.invoke(dataSource, setterValue);
}
return;
} catch (final ReflectiveOperationException ignored) {
}
}
}
}

shardingjdbc4.x初始化数据源过程
https://www.huangchaoyu.com/227567824.html
作者
hcy
发布于
2024年10月9日
更新于
2024年10月9日
许可协议