cn.mybatis.mp.routing.datasource.SpringRoutingDataSource Maven / Gradle / Ivy
package cn.mybatis.mp.routing.datasource;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import javax.sql.DataSource;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
/**
* 基于spring的动态数据源
*/
public class SpringRoutingDataSource extends AbstractRoutingDataSource {
private final Field resolvedDataSourcesField;
private final Field targetDataSourcesField;
public SpringRoutingDataSource() {
try {
resolvedDataSourcesField = AbstractRoutingDataSource.class.getDeclaredField("resolvedDataSources");
resolvedDataSourcesField.setAccessible(true);
targetDataSourcesField = AbstractRoutingDataSource.class.getDeclaredField("targetDataSources");
targetDataSourcesField.setAccessible(true);
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
}
}
@Override
protected String determineCurrentLookupKey() {
return DataSourceHolder.getCurrent();
}
@Override
protected DataSource determineTargetDataSource() {
DataSource dataSource = super.determineTargetDataSource();
if (dataSource instanceof GroupDataSource) {
return ((GroupDataSource) dataSource).loadBalance();
}
return dataSource;
}
public String getUrl() throws NoSuchMethodException {
DataSource dataSource = this.determineTargetDataSource();
String[] methodNames = new String[]{"getUrl", "getJdbcUrl"};
Throwable throwable = null;
for (String methodName : methodNames) {
try {
Method method = dataSource.getClass().getMethod(methodName);
return (String) method.invoke(dataSource);
} catch (Exception e) {
if (Objects.isNull(throwable)) {
throwable = e;
}
}
}
throw new NoSuchMethodException();
}
private String getGroupName(String key) {
if (!key.contains(Config.GROUP_SPLIT)) {
return null;
}
int index = key.lastIndexOf(Config.GROUP_SPLIT);
String no = key.substring(index + 1);
try {
Integer.parseInt(no);
} catch (NumberFormatException e) {
return null;
}
return key.substring(0, index);
}
/**
* 添加新的数据源
*
* @param key
* @param dataSource
*/
public void addNewDatasource(String key, DataSource dataSource) {
Map