动态数据源配置

307 阅读2分钟

动态数据源配置

/**
 * 项目名称:spring-demo
 * 类 名 称:DataSourceConfig
 * 类 描 述:多数据源配置
 * 创建时间:2022/4/7 9:49 下午
 *
 * @author gzw
 */
@Configuration
@Slf4j
public class DataSourceConfig {

    @ConfigurationProperties("spring.datasource.one")
    @Bean(initMethod = "init",destroyMethod = "close")
    public DruidDataSource oneDatasource(){
        log.debug("mysql one  druid data-source init...");
       return DruidDataSourceBuilder.create().build();
    }

    @ConfigurationProperties("spring.datasource.two")
    @Bean(initMethod = "init",destroyMethod = "close")
    public DruidDataSource twoDatasource(){
        log.debug("mysql two  druid data-source init...");
        return DruidDataSourceBuilder.create().build();
    }


    @ConfigurationProperties("spring.datasource.three")
    @Bean(initMethod = "init",destroyMethod = "close")
    public DruidDataSource threeDatasource(){
        log.debug("mysql three  druid data-source init...");
        return DruidDataSourceBuilder.create().build();
    }


    @Bean
    @Primary
    public DynamicDataSource dataSource(@Qualifier("oneDatasource") DataSource one,
                                        @Qualifier("twoDatasource") DataSource two,
                                        @Qualifier("threeDatasource") DataSource three) {
        Map<Object, Object> dsMap = Maps.newHashMapWithExpectedSize(INT_THREE);
        dsMap.put("MASTER", one);
        dsMap.put("SLAVE_2", two);
        dsMap.put("SLAVE_3", three);
        return new DynamicDataSource(dsMap, one);
    }
}

AbstractRoutingDataSource

/**
 * 项目名称:spring-demo
 * 类 名 称:DynamicDataSource
 * 类 描 述:动态数据源配置
 * 创建时间:2022/4/7 10:33 下午
 *
 * @author gzw
 */
@Slf4j
public class DynamicDataSource extends AbstractRoutingDataSource {


    private static final ThreadLocal<Stack<String>> DATA_SOURCE_KEY=new InheritableThreadLocal<>();


    public static void setDataSourceKey(String dataSourceKey){
        log.info("setDataSourceKey datasource{} ",dataSourceKey);
        Stack<String> stack = DATA_SOURCE_KEY.get();
        if(stack==null){
            stack= new Stack<>();
            DATA_SOURCE_KEY.set(stack);
        }
        stack.push(dataSourceKey);
    }

    public static void cleanDataSourceKey(){
        Stack<String> stack = DATA_SOURCE_KEY.get();
        if(stack!=null){
            stack.pop();
            if(stack.isEmpty()){
                DATA_SOURCE_KEY.remove();
            }
        }
    }

    @Override
    protected Object determineCurrentLookupKey() {
        Stack<String> stack = DATA_SOURCE_KEY.get();
        if(stack!=null){
            return stack.peek();
        }
        return null;
    }

    /**
     * 构造
     * @param dataSourceMap 数据源map
     * @param concurrentDatasource 默认数据源
     */
    public DynamicDataSource(Map<Object, Object> dataSourceMap,DataSource concurrentDatasource) {
        super.setDefaultTargetDataSource(concurrentDatasource);
        super.setTargetDataSources(dataSourceMap);
    }
}

注解

/**
 * 项目名称:spring-demo
 * 类 名 称:SpecDataSource
 * 类 描 述:多数据源指定某一数据源的注解
 * 创建时间:2022/5/23 6:48 下午
 *
 * @author gzw
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface SpecDataSource {

    String value();
}

AOP



/**
 * 项目名称:spring-demo
 * 类 名 称:MethodSwitchDataSourceAspectJ
 * 类 描 述:多数据源切换的AOP 作用在方法上
 * 创建时间:2022/5/23 6:52 下午
 *
 * @author gzw
 */
@Aspect
@Component
public class MethodSwitchDataSourceAspectJ implements Ordered {

    @Pointcut("@annotation(com.spring.demo.test.config.datasource.annotation.SpecDataSource)")
    public void pointcut() {

    }

    @Before(value = "pointcut() && @annotation(specDataSource)",argNames = "specDataSource")
    public void before(SpecDataSource specDataSource){
        DynamicDataSource.setDataSourceKey(specDataSource.value());
    }
    @After(value = "pointcut()")
    public void after(){
        DynamicDataSource.cleanDataSourceKey();
    }

    @Override
    public int getOrder() {
        return -2147483647;
    }
}
/**
 * 项目名称:spring-demo
 * 类 名 称:MethodSwitchDataSourceAspectJ
 * 类 描 述:多数据源切换的AOP 作用在类上
 * 创建时间:2022/5/23 6:52 下午
 *
 * @author gzw
 */
@Aspect
@Component
public class TypeSwitchDataSourceAspectJ implements Ordered {

    @Pointcut("@within(com.spring.demo.test.config.datasource.annotation.SpecDataSource)")
    public void pointcut() {

    }

    @Before(value = "pointcut() && @within(specDataSource)",argNames = "specDataSource")
    public void before(SpecDataSource specDataSource){
        DynamicDataSource.setDataSourceKey(specDataSource.value());
    }
    @After(value = "pointcut()")
    public void after(){
        DynamicDataSource.cleanDataSourceKey();
    }

    @Override
    public int getOrder() {
        return -2147483646;
    }
}