SoFunction
Updated on 2025-04-05

Methods of switching between Druid connection pool and multi-data source in SpringBoot

Multi-data source switching principle

The principle of multi-data source switching is mainly based on Spring's AbstractRoutingDataSource class. The AbstractRoutingDataSource class allows dynamic selection of data sources based on the runtime context. Its core lies in implementing the determineCurrentLookupKey method, which determines which data source is used for the current operation. AbstractRoutingDataSource The principle of implementing multi-data source switching:

1. Data source mapping

  • AbstractRoutingDataSourceA map (Map) is maintained internally to store the data source identifier (key) and the corresponding data source instance (value). This mapping allows quick search and acquisition of corresponding data sources based on the data source identification.

2. Determination of data source identification

  • AbstractRoutingDataSourceProvides an abstract methoddetermineCurrentLookupKey(), This method is used to determine the data source identifier that needs to be used. This method needs to be implemented by a subclass to return the data source identity that the current thread or request should use.

3. Selection and connection acquisition of data source

  • When the application needs to obtain a database connection,AbstractRoutingDataSourceofgetConnection()The method will be called. This method is called firstdetermineCurrentLookupKey()Method to obtain the current data source identifier, and then find the corresponding data source from the internal map based on this identifier.
  • Once the corresponding data source is found,AbstractRoutingDataSourceThe data source will be calledgetConnection()Method to get the actual database connection and return this connection to the application.

4. Implementation of data source switching

  • In order to realize dynamic switching of data sources, it is usually rewritten in subclasses.determineCurrentLookupKey()Method and determine the returned data source identity based on the current context (such as thread variables).
  • In addition, usuallyThreadLocalStorage the data source identifier of each thread so that each thread can switch the data sources independently without interfering with each other.

Implementation steps

1. Dependence

Introducing MySQL and Druid dependencies

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId></groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.2.6</version>
</dependency>

2. Configure the data source

existConfigure multiple data sources in the file.

spring:
  datasource:
    type: 
    druid:
      datasource1:
        url: jdbc:mysql://localhost:3306/master_db
        username: root
        password: password
        initial-size: 5
        min-idle: 5
        max-active: 20
        max-wait: 60000
      datasource2:
        url: jdbc:mysql://localhost:3306/slave_db
        username: root
        password: password
        initial-size: 5
        min-idle: 5
        max-active: 20
        max-wait: 60000

3. Create a data source configuration class

Create a configuration class to define the data source bean.

@Configuration
public class DataSourceConfig {

    @Bean
    @ConditionalOnProperty(prefix = "", name = "datasource1")
    @ConfigurationProperties(prefix = ".datasource1")
    public DataSource dataSource1() {
        return ().build();
    }

    @Bean
    @ConditionalOnProperty(prefix = "", name = "datasource2")
    @ConfigurationProperties(prefix = ".datasource2")
    public DataSource dataSource2() {
        return ().build();
    }

    @Bean
    @Primary
    public DataSource dynamicDataSource() {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        (dataSource1());
        Map<Object, Object> targetDataSources = new HashMap<>();
        ("dataSource1", dataSource1());
        ("dataSource2", dataSource2());
        (targetDataSources);
        return dynamicDataSource;
    }
}

4. Implement AbstractRoutingDataSource

Create an inherited fromAbstractRoutingDataSourceclass and implementdetermineCurrentLookupKeymethod.

public class DynamicDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        return ();
    }
}

5. Create DataSourceContextHolder

Create a tool class to save the data source information of the current thread.

public class DataSourceContextHolder {

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

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

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

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

6. AOP dynamically switches data sources

Use AOP to switch the data source before and after method execution.

import ;
import ;
import ;
import ;
import ;
import ;

@Aspect
@Component
public class DataSourceAspect {
	// Cross-cut points on a method or class    @Pointcut("@annotation(dataSource) || @within(dataSource)")
    public void dataSourcePointcut(DataSource dataSource) {}

    @Before("dataSourcePointcut(dataSource)")
    public void switchDataSource(JoinPoint joinPoint, DataSource dataSource) {
        // Get the data source identifier from the annotation        String dataSourceKey = ();
        // Switch to the specified data source        (dataSourceKey);
    }

    @AfterReturning(pointcut = "dataSourcePointcut(dataSource)", returning = "result")
    public void restoreDataSource(JoinPoint joinPoint, DataSource dataSource, Object result) {
        // Restore the default data source (optional)        ();
    }
}

/**
 * Custom annotations
 */
@Target({, })
@Retention()
public @interface DataSource {

    String value() default "dataSource1";
}

7. Use custom annotations

Use custom annotations on methods that require switching data sources.

Notice

  • The logic of data source switching should be as simple and efficient as possible to avoid negative impacts on application performance.
  • When switching data sources, you need to pay attention to transaction management issues and ensure that only the same data source is used in the same transaction.

This is the article about how to switch between Druid connection pool and multi-data source in SpringBoot. For more related content on SpringBoot Druid and data source switching, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!