文章目录前言一、多数据源配置与切换方案二、实现步骤1. 创建多个 DataSource 配置类2. 创建 DataSource 配置类3. 创建动态数据源路由类4. 实现 DynamicDataSource 类5. 创建 DataSourceContextHolder 来存储当前的数据源标识6. AOP 方式切换数据源7. 自定义注解来指定数据源8. 在 Service 层使用注解指定数据源总结前言在 Spring Boot 中实现多数据源连接和切换可以通过以下几种方案来实现具体取决于项目的需求、数据库的使用模式和管理的复杂性。以下是一个常见的多数据源切换的实现方案使用 AbstractRoutingDataSource 来动态选择数据源。一、多数据源配置与切换方案在多数据源场景中通常有如下步骤配置多个数据源的DataSourcebean。使用AbstractRoutingDataSource来动态切换数据源。使用ThreadLocal存储当前的数据库类型或数据源标识符。配置数据源切换的逻辑例如基于当前的用户、请求路径、服务标识等来选择不同的数据源。二、实现步骤1. 创建多个DataSource配置类首先为每个数据源创建单独的配置类通常你会在application.yml或application.properties中配置每个数据源的连接信息。spring: datasource: # 默认数据源配置 primary: url: jdbc:mysql://localhost:3306/primary_db username: root password: password driver-class-name: com.mysql.cj.jdbc.Driver hikari: maximum-pool-size: 10 # 第二数据源配置 secondary: url: jdbc:mysql://localhost:3306/secondary_db username: root password: password driver-class-name: com.mysql.cj.jdbc.Driver hikari: maximum-pool-size: 102. 创建DataSource配置类Configuration EnableTransactionManagement public class DataSourceConfig { Bean(name primaryDataSource) Primary ConfigurationProperties(prefix spring.datasource.primary) public DataSource primaryDataSource() { return DataSourceBuilder.create().build(); } Bean(name secondaryDataSource) ConfigurationProperties(prefix spring.datasource.secondary) public DataSource secondaryDataSource() { return DataSourceBuilder.create().build(); } }3. 创建动态数据源路由类AbstractRoutingDataSource允许我们在运行时根据某些条件动态选择数据源。Configuration public class DynamicDataSourceConfig { Autowired Qualifier(primaryDataSource) private DataSource primaryDataSource; Autowired Qualifier(secondaryDataSource) private DataSource secondaryDataSource; Bean public DataSource dataSource() { // 创建一个路由数据源 DynamicDataSource dataSource new DynamicDataSource(); dataSource.setDefaultTargetDataSource(primaryDataSource); // 默认数据源 MapObject, Object targetDataSources new HashMap(); targetDataSources.put(primary, primaryDataSource); targetDataSources.put(secondary, secondaryDataSource); dataSource.setTargetDataSources(targetDataSources); return dataSource; } }4. 实现DynamicDataSource类DynamicDataSource是继承自AbstractRoutingDataSource它通过determineCurrentLookupKey()方法来动态确定当前的数据源。public class DynamicDataSource extends AbstractRoutingDataSource { // 从 ThreadLocal 获取当前的数据库标识 Override protected Object determineCurrentLookupKey() { return DataSourceContextHolder.getDataSourceType(); } }5. 创建DataSourceContextHolder来存储当前的数据源标识使用ThreadLocal来保持当前线程的数据库标识以便在不同的数据源之间切换。public class DataSourceContextHolder { // 使用 ThreadLocal 存储当前线程的数据源标识 private static final ThreadLocalString contextHolder new ThreadLocal(); public static void setDataSourceType(String dataSourceType) { contextHolder.set(dataSourceType); } public static String getDataSourceType() { return contextHolder.get(); } public static void clearDataSourceType() { contextHolder.remove(); } }6. AOP 方式切换数据源为了在运行时动态切换数据源通常会使用 AOP 切面来拦截方法执行并指定数据源。Aspect Component public class DataSourceAspect { // 通过注解来指定使用哪个数据源 Before(annotation(dataSource)) public void switchDataSource(DataSourceType dataSource) { // 切换数据源 DataSourceContextHolder.setDataSourceType(dataSource.value()); } After(annotation(dataSource)) public void clearDataSource(DataSourceType dataSource) { // 清理数据源标识避免影响其他线程 DataSourceContextHolder.clearDataSourceType(); } }7. 自定义注解来指定数据源创建一个自定义注解DataSourceType用于指定当前方法执行时需要使用的数据源。Target(ElementType.METHOD) Retention(RetentionPolicy.RUNTIME) public interface DataSourceType { String value() default primary; // 数据源标识默认使用primary数据源 }8. 在 Service 层使用注解指定数据源在 Service 层可以使用刚才创建的DataSourceType注解来指定不同的方法使用不同的数据源。Service public class UserService { DataSourceType(primary) public ListUser getPrimaryUsers() { // 查询主数据库 return userRepository.findAll(); } DataSourceType(secondary) public ListUser getSecondaryUsers() { // 查询次数据库 return secondaryUserRepository.findAll(); } }总结数据源配置为每个数据源配置DataSourceBean。动态数据源路由使用AbstractRoutingDataSource来实现动态切换数据源。ThreadLocal存储使用ThreadLocal存储和获取当前线程的数据源标识。AOP切换数据源使用 AOP 来拦截方法并切换数据源。注解方式指定数据源通过自定义注解来指定方法使用的具体数据源。这种方式比较灵活能够在运行时根据业务需求选择不同的数据源适用于多数据源的场景尤其是分库分表、读写分离等复杂应用场景。