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); }
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) { } } } }
|