SpringBoot如何在运行时动态添加数据源 - yxbook/notes GitHub Wiki

Spring提供了AbstractRoutingDataSource用于动态路由数据源第一种场景继承AbstractRoutingDataSource类并覆写其protected abstract Object determineCurrentLookupKey()即可;

而第二种场景我们直接覆写protected DataSource determineTargetDataSource方法即可原理可看下AbstractRoutingDataSource对应源码比较简单不做赘述。



        <!--动态数据源-->
        <!-- https://mvnrepository.com/artifact/com.alibaba/druid-spring-boot-starter -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.5</version>
        </dependency>

直接上干货import com.fizz.utils.spring.SpringUtils;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import javax.sql.DataSource;
 
public class DynamicDataSource extends AbstractRoutingDataSource {
 
  private static final ThreadLocal<DataSource> dataSource = ThreadLocal.withInitial(() -> (DataSource) SpringUtils.getBean("defaultDataSource"));
 
  public static void setDataSource(DataSource dataSource) {
    DynamicDataSource.dataSource.set(dataSource);
  }
 
  public static DataSource getDataSource() {
    return DynamicDataSource.dataSource.get();
  }
 
  @Override
  protected Object determineCurrentLookupKey() {
    return null;
  }
 
  @Override
  protected DataSource determineTargetDataSource() {
    return getDataSource();
  }
 
  public static void clear() {
    DynamicDataSource.dataSource.remove();
  }
}






import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import javax.sql.DataSource;
import java.util.HashMap;
 
@Configuration
public class DataSourceConfig {
 
  @Bean
  @ConfigurationProperties("spring.datasource.druid")
  public DataSource defaultDataSource() {
    return DruidDataSourceBuilder.create().build();
  }
 
  @Bean
  @Primary
  public DynamicDataSource dataSource() {
    DynamicDataSource dynamicDataSource = new DynamicDataSource();
    dynamicDataSource.setTargetDataSources(new HashMap<>());
    return dynamicDataSource;
  }
}


使用时直接调用DynamicDataSource.setDataSource(DataSource dataSource)方法即可使用完后调用DynamicDataSource.clear()防止内存泄漏并重置默认数据源附上详细使用方法DruidDataSource druidDataSource = new DruidDataSource();
    druidDataSource.setUrl("jdbc:mysql://localhost:3306/sys?characterEncoding=utf-8&useSSL=false&serverTimezone=UTC&useAffectedRows=true");
    druidDataSource.setUsername("root");
    druidDataSource.setPassword("root");
    DynamicDataSource.setDataSource(druidDataSource);
    此时数据源已切换到druidDataSource调用自己的业务方法即可使用完后调用DynamicDataSource.clear();重置为默认数据源附上工具类SpringUtilsimport lombok.Getter;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
 
@Component
public final class SpringUtils implements ApplicationContextAware {
 
  @Getter
  private static ApplicationContext applicationContext;
 
  @Override
  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    if (SpringUtils.applicationContext == null) {
      SpringUtils.applicationContext = applicationContext;
    }
  }
 
  public static <T> T getBean(Class<T> clazz) {
    return SpringUtils.applicationContext.getBean(clazz);
  }
 
  public static Object getBean(String name) {
    return SpringUtils.applicationContext.getBean(name);
  }
 
  public static String getProperty(String key) {
    return SpringUtils.applicationContext.getEnvironment().getProperty(key);
  }
}
⚠️ **GitHub.com Fallback** ⚠️