1、yml配置文件
2、添加数据源选择注解
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {
String name() default "";
}
3、多数据源名称
public interface DataSourceNames {
String FIRST = "first";
String SECOND = "second";
String THIRD = "third";
}
4、动态数据源
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import javax.sql.DataSource;
import java.util.Map;
public class DynamicDataSource extends AbstractRoutingDataSource {
private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();
public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {
super.setDefaultTargetDataSource(defaultTargetDataSource);
super.setTargetDataSources(targetDataSources);
super.afterPropertiesSet();
}
@Override
protected Object determineCurrentLookupKey() {
return getDataSource();
}
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();
}
}
5、数据源切面处理
import com.base.datasources.DataSourceNames;
import com.base.datasources.DynamicDataSource;
import com.base.datasources.annotation.DataSource;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
@Slf4j
@Aspect
@Component
public class DataSourceAspect implements Ordered {
@Pointcut("@annotation(com.base.datasources.annotation.DataSource)")
public void dataSourcePointCut() {
}
@Around("dataSourcePointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
DataSource dataSource = method.getAnnotation(DataSource.class);
if (dataSource == null) {
DynamicDataSource.setDataSource(DataSourceNames.FIRST);
log.debug("SET DATASOURCE IS " + DataSourceNames.FIRST);
} else {
DynamicDataSource.setDataSource(dataSource.name());
log.debug("SET DATASOURCE IS " + dataSource.name());
}
try {
return point.proceed();
} finally {
DynamicDataSource.clearDataSource();
log.debug("CLEAN DATASOURCE");
}
}
@Override
public int getOrder() {
return 1;
}
}
6、配置多数据源
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
public class DynamicDataSourceConfig {
@Bean(name = "firstDataSource")
@Qualifier("firstDataSource")
@ConfigurationProperties("spring.datasource.druid.first")
public DataSource firstDataSource() {
return DruidDataSourceBuilder.create().build();
}
/***
* 多数据源支持请开启次配置
*/
@Bean(name = "secondDataSource")
@Qualifier("secondDataSource")
@ConfigurationProperties("spring.datasource.druid.second")
public DataSource secondDataSource() {
return DruidDataSourceBuilder.create().build();
}
/**
* 第三数据源
*/
@Bean(name = "thirdDataSource")
@Qualifier("thirdDataSource")
@ConfigurationProperties("spring.datasource.druid.third")
public DataSource thirdDataSource() {
return DruidDataSourceBuilder.create().build();
}
@Bean
@Primary
public DynamicDataSource dataSource(DataSource firstDataSource, DataSource secondDataSource, DataSource thirdDataSource) {
/*
* map中2个元素,与2的n次方最接近的数是2,但是这里如果设置容量为2的话 2/2=1,
* 已经超过默认加载因子(0.75)的大小了。因此会resize一次,变成4。所以最优的值是4。
*
* https://www.cnblogs.com/tiancai/p/9558895.html
*/
Map<Object, Object> targetDataSources = new HashMap<>(4);
targetDataSources.put(DataSourceNames.FIRST, firstDataSource);
targetDataSources.put(DataSourceNames.SECOND, secondDataSource);
targetDataSources.put(DataSourceNames.THIRD, thirdDataSource);
return new DynamicDataSource(firstDataSource, targetDataSources);
}
}
7、启动类添加配置
8、调用
方法上添加@DataSource注解, name属性指定数据源名称
不添加@DataSource注解即默认第一个数据源
9、测试
依赖
<!-- 切面处理 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- lombok可使代码更简洁 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>