spring/springboot 整合注解切换数据源

发布时间 2023-09-01 17:12:50作者: 昨晚的梦

springboot 整合注解切换数据源
1、Spring Boot的配置文件

# 数据源1
spring.datasource.druid.one.url=jdbc:mysql://localhost:3306/db1
spring.datasource.druid.one.username=root
spring.datasource.druid.one.password=123456

# 数据源2
spring.datasource.druid.two.url=jdbc:mysql://localhost:3306/db2
spring.datasource.druid.two.username=root
spring.datasource.druid.two.password=123456

2、创建数据源配置类
创建一个数据源配置类,用于配置多个数据源:

@Configuration
public class DataSourceConfig {

    @Bean(name = "oneDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.druid.one")
    public DataSource dataSourceOne() {
        return new DruidDataSource();
    }

    @Bean(name = "twoDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.druid.two")
    public DataSource dataSourceTwo() {
        return new DruidDataSource();
    }

}

3、创建动态数据源工厂类
创建一个动态数据源工厂类,用于根据不同的注解切换不同的数据源:

public class DynamicDataSource extends AbstractRoutingDataSource {

    private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();

    @Override
    protected Object determineCurrentLookupKey() {
        return contextHolder.get();
    }

    public static void setDataSourceKey(String dataSourceKey) {
        contextHolder.set(dataSourceKey);
    }

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

}
4、创建数据源切换注解
创建一个自定义的注解,用于标记需要切换的数据源:
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface UseDataSource {
    String value();
}

5、创建数据源切换切面类
创建一个切面类,用于根据注解的值切换数据源:

@Aspect
@Component
public class DataSourceAspect {

    @Around("@annotation(useDataSource)")
    public Object switchDataSource(ProceedingJoinPoint joinPoint, UseDataSource useDataSource) throws Throwable {
        try {
            DynamicDataSource.setDataSourceKey(useDataSource.value());
            return joinPoint.proceed();
        } finally {
            DynamicDataSource.clearDataSourceKey();
        }
    }

}

6、使用注解切换数据源
在需要切换数据源的方法或类上添加@UseDataSource注解,并指定需要切换的数据源的名称:

@Service
public class UserService {
    @Autowired
    private UserDao oneUserDao; // 使用数据源1的UserDao操作数据库1中的用户信息。
    @Autowired
    private UserDao twoUserDao; // 使用数据源2的UserDao操作数据库2中的用户信息。
    @UseDataSource("one") // 切换到数据源1。

spring 整合注解切换数据源
1、Spring的配置文件

<bean id="dataSource1" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <!-- 数据源1的配置 -->
</bean>

<bean id="dataSource2" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <!-- 数据源2的配置 -->
</bean>

2、创建数据源切换注解
创建一个自定义的注解,例如@DataSource,用于指定使用哪个数据源

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface DataSource {
    String value();
}

3、创建数据源切换切面
创建一个切面类,用于根据注解的值切换数据源

@Aspect
@Component
public class DataSourceAspect {
    @Around("@annotation(com.example.demo.annotation.DataSource)")
    public Object switchDataSource(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        DataSource ds = method.getAnnotation(DataSource.class);
        if (ds == null) {
            throw new RuntimeException("无法切换数据源,请在方法上添加@DataSource注解,并指定数据源名");
        }
        String dataSourceName = ds.value();
        DataSourceContextHolder.setDataSource(dataSourceName);
        return joinPoint.proceed();
    }
}

创建数据源上下文持有者类
创建一个数据源上下文持有者类,用于保存当前线程的数据源信息:

public class DataSourceContextHolder {
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
    public static void setDataSource(String dataSourceName) {
        contextHolder.set(dataSourceName);
    }
    public static String getDataSource() {
        return contextHolder.get();
    }
    public static void clearDataSource() {
        contextHolder.remove();
    }
}

注入数据源Bean到Spring容器中
将多个数据源的Bean注入到Spring容器中:

@Configuration
public class DataSourceConfig {
    @Bean(name = "dataSource1")
    public DataSource dataSource1() {
        return new BasicDataSource();
    }
    @Bean(name = "dataSource2")
    public DataSource dataSource2() {
        return new BasicDataSource();
    }
}