根据这段源码可以看出,每次执⾏时,都会遍历targetDataSources内的所有元素并赋值给resolvedDataSources;这样如果我们在外部程序新增⼀个新的数据源,都会添加到内部使⽤,从⽽实现数据源的动态加载。
继承该抽象类的时候,必须实现⼀个抽象⽅法:protected abstract Object determineCurrentLookupKey(),该⽅法⽤于指定到底需要使⽤哪⼀个数据源。
⼆、实现多数据源切换和动态数据源加载
A - 配置⽂件信息
server:
port: 18080
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
# 主数据源
master-db:
driverClassName: sql.jdbc.Driver
url: jdbc:mysql://192.168.223.129:13306/test_master_db?characterEncoding=utf-8 username: josen
password: josen
# 从数据源
slave-db:
driverClassName: sql.jdbc.Driver
springboot aopurl: jdbc:mysql://192.168.223.129:13306/test_slave_db?characterEncoding=utf-8 username: josen
password: josen
mybatis:
mapper-locations: classpath:mapper/*.xml
logging:
path: ./logs/mydemo20201105.log
level:
demo20201105: debug
maven 依赖
org.springframework.boot
spring-boot-starter-aop
com.alibaba
druid-spring-boot-starter
1.1.10
org.springframework.boot
spring-boot-starter-web
mybatis-spring-boot-starter
2.1.3
mysql
mysql-connector-java
runtime
org.projectlombok
lombok
true
B - 编码实现
1、创建⼀个DynamicDataSource类,继承AbstractRoutingDataSource抽象类,实现determineCurrentLookupKey⽅法,通过该⽅法指定当前使⽤哪个数据源;
2、 在DynamicDataSource类中通过ThreadLocal维护⼀个全局数据源名称,后续通过修改该名称实现动态切换;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import javax.sql.DataSource;
import java.util.Map;
/**
* @ClassName DynamicDataSource
* @Description 设置动态数据源
* @Author Josen
* @Date 2020/11/5 14:28
**/
public class DynamicDataSource extends AbstractRoutingDataSource {
// 通过ThreadLocal维护⼀个全局唯⼀的map来实现数据源的动态切换
private static final ThreadLocal contextHolder = new ThreadLocal<>();
public DynamicDataSource(DataSource defaultTargetDataSource, Map targetDataSources) {
super.setDefaultTargetDataSource(defaultTargetDataSource);
super.setTargetDataSources(targetDataSources);
super.afterPropertiesSet();
}
/
**
* 指定使⽤哪⼀个数据源
*/
@Override
protected Object determineCurrentLookupKey() {
return getDataSource();
}
public static void setDataSource(String dataSource) {
contextHolder.set(dataSource);
public static String getDataSource() {
();
}
public static void clearDataSource() {
}
}
3、创建DynamicDataSourceConfig类,引⼊application.yaml配置的多个数据源信息,构建多个数据源;import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import org.t.properties.ConfigurationProperties;
import t.annotation.Bean;
import t.annotation.Configuration;
import t.annotation.Primary;
import org.springframework.stereotype.Component;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
/**
* @ClassName DynamicDataSourceConfig
* @Description 引⼊动态数据源,构建数据源
* @Author Josen
* @Date 2020/11/5 14:23
**/
@Configuration
@Component
public class DynamicDataSourceConfig {
/**
* 读取application配置,构建master-db数据源
*/
@Bean
@ConfigurationProperties("spring.datasource.druid.master-db")
public DataSource myMasterDataSource(){
ate().build();
/**
* 读取application配置,构建slave-db数据源
*/
@Bean
@ConfigurationProperties("spring.datasource.druid.slave-db")
public DataSource mySlaveDataSource(){
ate().build();
}
/**
* 读取application配置,创建动态数据源
*/
@Bean
@Primary
public DynamicDataSource dataSource(DataSource myMasterDataSource, DataSource mySlaveDataSource) {
Map targetDataSources = new HashMap<>();
targetDataSources.put("master-db",myMasterDataSource);
targetDataSources.put("slave-db", mySlaveDataSource);
// myMasterDataSource=默认数据源
// targetDataSources=⽬标数据源(多个)
return new DynamicDataSource(myMasterDataSource, targetDataSources);
}
}
4、 创建MyDataSource⾃定义注解,后续AOP通过该注解作为切⼊点,通过获取使⽤该注解存⼊不同的值动态切换指定的数据源;import java.lang.annotation.*;
/**
* ⾃定义数据源注解
* 在需要切换数据源的Service层⽅法上添加此注解,指定数据源名称
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyDataSource {
String name() default "";
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论