Implementing Multiple Data Sources with Druid in Spring Boot

Componant Implementation
DataSource Annotation DataSource.java
AspectJ Implementation DataSourceAspect.java
Data Source Constants DataSourceConstants.java
Dynamic Data Source DynamicDataSource.java
Configuration DataSourceConfig.java

DataSource Annotation


package com.example.datasource.config;

import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {
    String name() default "";
}

AspectJ Implementation


package com.example.datasource.config;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class DataSourceInterceptor implements Ordered {

    @Pointcut("@annotation(DataSource)")
    public void dataSourcePointcut() {}

    @Around("dataSourcePointcut()")
    public Object switchDataSource(ProceedingJoinPoint pjp) throws Throwable {
        DataSource annotation = getDataSourceAnnotation(pjp);
        String dsName = annotation != null ? annotation.name() : DataSourceConstants.PRIMARY;
        
        DynamicDataSource.setCurrentDataSource(dsName);
        try {
            return pjp.proceed();
        } finally {
            DynamicDataSource.clearDataSource();
        }
    }

    private DataSource getDataSourceAnnotation(ProceedingJoinPoint pjp) {
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        return signature.getMethod().getAnnotation(DataSource.class);
    }

    @Override
    public int getOrder() {
        return 1;
    }
}

Data Source Constants


package com.example.datasource.config;

public class DataSourceConstants {
    public static final String PRIMARY = "primary";
    public static final String SECONDARY = "secondary";
}

Dynamic Data Source


package com.example.datasource.config;

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import java.util.Map;
import com.alibaba.druid.pool.DruidDataSource;

public class DynamicDataSource extends AbstractRoutingDataSource {
    private static final ThreadLocal<string> currentDataSource = new ThreadLocal<>();

    public DynamicDataSource(DruidDataSource defaultDs, Map<object object=""> targetDataSources) {
        super.setDefaultTargetDataSource(defaultDs);
        super.setTargetDataSources(targetDataSources);
        super.afterPropertiesSet();
    }

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

    public static void setCurrentDataSource(String dsName) {
        currentDataSource.set(dsName);
    }

    public static void clearDataSource() {
        currentDataSource.remove();
    }
}
</object></string>

Configuration


package com.example.datasource.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import java.util.HashMap;
import java.util.Map;

@Configuration
public class DataSourceConfig {

    @Bean
    @ConfigurationProperties("spring.datasource.primary")
    public DruidDataSource primaryDataSource() {
        return new DruidDataSource();
    }

    @Bean
    @ConfigurationProperties("spring.datasource.secondary")
    public DruidDataSource secondaryDataSource() {
        return new DruidDataSource();
    }

    @Bean
    @Primary
    public DynamicDataSource routingDataSource(
            DruidDataSource primaryDataSource,
            DruidDataSource secondaryDataSource) {
        
        Map<object object=""> dataSources = new HashMap<>();
        dataSources.put(DataSourceConstants.PRIMARY, primaryDataSource);
        dataSources.put(DataSourceConstants.SECONDARY, secondaryDataSource);
        
        return new DynamicDataSource(primaryDataSource, dataSources);
    }
}
</object>

Tags: druid spring-boot aop multi-datasource java

Posted on Thu, 13 Aug 2026 16:42:52 +0000 by sweetmaster