AbstractRoutingDataSource
该类充当了DataSource的路由中介, 能有在运行时, 根据某种key值来动态切换到真正的DataSource上。
public abstract class AbstractRoutingDataSource extends AbstractDataSource implements InitializingBean {
private Map<Object, Object> targetDataSources;
private Object defaultTargetDataSource;
/* */
public void setTargetDataSources(Map<Object, Object> targetDataSources) {
this.targetDataSources = targetDataSources;
}
/* */
public void setDefaultTargetDataSource(Object defaultTargetDataSource) {
this.defaultTargetDataSource = defaultTargetDataSource;
}
/* */
protected abstract Object determineCurrentLookupKey();
}
复制代码
具体实现
1、自定义 DynamicDataSource 类继承自AbstractRoutingDataSource
public class DynamicDataSource extends AbstractRoutingDataSource{
@Override
protected Object determineCurrentLookupKey() {
return DataSourceHolder.getDataSource();
}
}
复制代码
2、定义 DataSourceHolder 类。
ThreadLocal :为每个线程创建独立的局部变量副本,线程之间的ThradLocal互不影响(不同线程使用的不同的数据库,互不影响,线程安全)。
public class DataSourceHolder {
private static ThreadLocal<String> threadLocal = new ThreadLocal<>();
public static String getDataSource() {
return threadLocal.get();
}
public static void setDataSource(String dataSourceName) {
threadLocal.set(dataSourceName);
}
public static void removeDataSource() {
threadLocal.remove();
}
}
复制代码
3、加载多数据源
@Configuration
public class DynamicDataConfig {
@Bean(name = "default") // 初始化bean
@ConfigurationProperties(prefix = "spring.datasource") //加载默认数据源
public DataSource createDefaultTargetDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@Primary // 指定使用 DynamicDataSource 来作为系统 dataSource 数据源
public DynamicDataSource createDataSource(@Qualifier("default") DataSource defaultDataSource) {
DynamicDataSource dynamicDataSource = new DynamicDataSource();
dynamicDataSource.setDefaultTargetDataSource(defaultDataSource);
dynamicDataSource.setTargetDataSources(getTargetDataSources());
return dynamicDataSource;
}
/* 初始化 targetDataSources */
public Map<Object, Object> getTargetDataSources() {
Map<Object, Object> targetDataSources = new HashMap();
targetDataSources.put("test_2",DataSourceBuilder.create()
.url("jdbc:mysql://localhost:3306/test_2")
.username("root")
.password("yangyang")
.driverClassName("com.mysql.jdbc.Driver")
.build());
return targetDataSources;
}
}
复制代码
4、切换数据源 根据 targetDataSources 的 key 来实现切换数据源(切面调用,实现切换)
DataSourceHolder.setDataSource("test_2");
复制代码