SpringBoot 动态数据源

DbConfig.java

package com.demo.config;

import com.demo.db.DynamicDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

/**
 * DalConfig
 *
 * @since 2024/10/8
 */
@Configuration
@ConditionalOnMissingBean(SqlSessionFactoryBean.class)
public class DbConfig {

//    @Primary
    @Bean("BBZTechSupportDB")
    public DataSource dataSource(DalDbConfig dalDbConfig) throws Exception {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://10.32.25.13:3306/BBZTechSupportDB");
        dataSource.setUsername("root");
        dataSource.setPassword(null);
        return dataSource;
    }

    @Bean("edpbusinesssupportbillmanagementdb")
    public DataSource dataSource1(DalDbConfig dalDbConfig) throws Exception {
        return dalDataSourceFactory.getOrCreateDataSource(dalDbConfig.getEdpbusinesssupportbillmanagementdb());
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://10.32.25.13:3306/mysql");
        dataSource.setUsername("root");
        dataSource.setPassword(null);
        return dataSource;
    }


    @Bean
    @ConditionalOnMissingBean
    public SqlSessionFactory sqlSessionFactory(DataSource dynamicDataSource, ResourceLoader resourceLoader) throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dynamicDataSource);
        sessionFactory.setConfigLocation(resourceLoader.getResource("classpath:mybatis-config.xml"));
        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:/mapper/**/*.xml"));
        return sessionFactory.getObject();
    }

    @Bean
    public DataSource dynamicDataSource(@org.springframework.beans.factory.annotation.Qualifier("BBZTechSupportDB") DataSource BBZTechSupportDB,
                                        @org.springframework.beans.factory.annotation.Qualifier("edpbusinesssupportbillmanagementdb") DataSource mysql) {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put("BBZTechSupportDB", BBZTechSupportDB);
        targetDataSources.put("edpbusinesssupportbillmanagementdb", mysql);
        dynamicDataSource.setDefaultTargetDataSource(BBZTechSupportDB);
        dynamicDataSource.setTargetDataSources(targetDataSources);
        return dynamicDataSource;
    }
}

DataSourceContextHolder.java

package com.demo.db;

/**
 * DataSourceContextHolder
 *
 * @since 2025/2/20
 */
public class DataSourceContextHolder {
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();

    public static void setDataSource(String dataSource) {
        contextHolder.set(dataSource);
    }

    public static String getDataSource() {
        return contextHolder.get();
    }

    public static void clearDataSource() {
        contextHolder.remove();
    }
}

DataSourceSwitch.java

package com.demo.db;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * DataSourceSwitch
 *
 * @since 2025/2/20
 */
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface DataSourceSwitch {
    String value() default "BBZTechSupportDB";
}

DataSourceSwitchAspect.java

package com.demo.db;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * DataSourceSwitchAspect
 *
 * @since 2025/2/20
 */
@Aspect
@Component
public class DataSourceSwitchAspect {

    @Before("within(@com.demo.db.DataSourceSwitch *) && execution(* *(..))")
    public void before(JoinPoint point) {
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        DataSourceSwitch dataSourceSwitch = method.getAnnotation(DataSourceSwitch.class);
        if (dataSourceSwitch != null) {
            DataSourceContextHolder.setDataSource(dataSourceSwitch.value());
        } else {
            Class<?> targetClass = point.getTarget().getClass();

            String name = targetClass.getName();
            if (name.contains("proxy")) {
                targetClass = targetClass.getInterfaces()[0];
            }
            // 获取类上的注解
            dataSourceSwitch = targetClass.getAnnotation(DataSourceSwitch.class);
            if (dataSourceSwitch != null) {
                DataSourceContextHolder.setDataSource(dataSourceSwitch.value());
            }
        }
    }

    @Before("within(@com.demo.db.DataSourceSwitch *) && execution(* *(..))")
    public void after(JoinPoint point) {
        DataSourceContextHolder.clearDataSource();
    }
}

DynamicDataSource.java

package com.demo.db;

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

/**
 * DynamicDataSource
 *
 * @since 2025/2/20
 */
public class DynamicDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceContextHolder.getDataSource();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值