spring多数据源的如何切换?

由于是spring项目,可以借助 spring 的DataSource 对象去管理,大体思路是创建一个类(比如MyRoutingDataSource)实现该接口,替换spring原有的DataSource 对象,通过MyRoutingDataSource 管理需要spring真实的干活的数据源,这是属于哪种设计模式??

spring jdbc 已经考虑到了,继承spring中 AbstractRoutingDataSource 抽象类实现determineCurrentLookupKey 方法,setTargetDataSources方法用map形式传入所需要切换数据源,是模板方法设计模式??

在Spring框架中实现多数据源配置并切换通常涉及以下步骤:

1.定义数据源

在Spring配置文件中(XML或Java Config)定义多个DataSource bean。

 2.配置JPA或MyBatis

如果你使用JPA,你可能需要为每个数据源配置一个EntityManagerFactoryTransactionManager。如果你使用MyBatis,你可能需要为每个数据源配置一个SqlSessionFactorySqlSessionTemplate

3.使用@Qualifier 或 @Primary

当你有多个相同类型的bean时,你可以使用@Qualifier注解来指定要注入的bean。或者,你可以使用@Primary注解来标记一个数据源作为主要的,以便在不需要明确指定时自动注入。

4.实现数据源路由

数据源路由是实现多数据源切换的关键。你可以通过继承AbstractRoutingDataSource来创建自定义的数据源,该数据源可以根据当前线程或请求上下文中的某个标识符来切换数据源。

5.使用AOP或拦截器设置数据源

在请求处理之前,你可以使用AOP或拦截器来设置当前线程的数据源标识符。这样,当数据访问层(如JPA仓库或MyBatis Mapper)尝试获取数据源时,它将通过你的自定义数据源路由逻辑来获取正确的数据源。

示例代码

自定义数据源路由
public class DynamicDataSource extends AbstractRoutingDataSource {  
  
    @Override  
    protected Object determineCurrentLookupKey() {  
        // 这里可以根据需要返回不同的数据源标识符  
        // 例如,从ThreadLocal中获取当前线程的数据源标识符  
        return DataSourceContextHolder.getCurrentDataSource();  
    }  
}  
  
// 用于保存当前线程的数据源标识符的工具类  
public class DataSourceContextHolder {  
  
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();  
  
    public static void setCurrentDataSource(String dataSource) {  
        contextHolder.set(dataSource);  
    }  
  
    public static String getCurrentDataSource() {  
        return contextHolder.get();  
    }  
  
    public static void clearCurrentDataSource() {  
        contextHolder.remove();  
    }  
}
配置数据源
@Configuration  
public class DataSourceConfig {  
  
    @Bean(name = "primaryDataSource")  
    @ConfigurationProperties(prefix = "spring.datasource.primary")  
    public DataSource primaryDataSource() {  
        // ... 配置并返回DataSource 
        return DataSourceBuilder.create().build(); 
    }  
  
    @Bean(name = "secondaryDataSource")  
    @ConfigurationProperties(prefix = "spring.datasource.secondary")  
    public DataSource secondaryDataSource() {  
        // ... 配置并返回DataSource  
        return DataSourceBuilder.create().build();
    }  
  
    @Bean(name = "dataSource")  
    public DataSource dynamicDataSource() {  
        DynamicDataSource dataSource = new DynamicDataSource();  
        Map<Object, Object> targetDataSources = new HashMap<>();  
        targetDataSources.put("primary", primaryDataSource());  
        targetDataSources.put("secondary", secondaryDataSource());  
        dataSource.setTargetDataSources(targetDataSources);  
        dataSource.setDefaultTargetDataSource(primaryDataSource());  
        return dataSource;  
    }  
  
    // 配置其他必要的组件,如EntityManagerFactory和TransactionManager(如果需要)  
}


使用AOP或拦截器设置数据源

@Aspect  
@Component  
public class DataSourceAspect {  
  
    @Pointcut("@annotation(customDataSource)")  
    public void dataSourcePointcut(CustomDataSource customDataSource) {}  
  
    @Before("dataSourcePointcut(customDataSource)")  
    public void switchDataSource(JoinPoint joinPoint, CustomDataSource customDataSource) {  
        DataSourceContextHolder.setCurrentDataSource(customDataSource.value());  
    }  
  
    @After("@annotation(customDataSource)")  
    public void restoreDataSource(JoinPoint joinPoint, CustomDataSource customDataSource) {  
        DataSourceContextHolder.clearCurrentDataSource();  
    }  
}  
  
// 自定义注解,用于指定数据源  
@Target({ElementType.METHOD, ElementType.TYPE})  
@Retention(RetentionPolicy.RUNTIME)  
public @interface CustomDataSource {  
  
    String value() default "primary";  
}


现在,你可以在需要指定数据源的方法上使用@CustomDataSource注解来切换数据源。在方法执行之前,AOP切面将设置当前线程的数据源标识符,并在方法执行后清除它。这样,数据访问层就可以通过DynamicDataSource获取正确的数据源了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值