一、分析AbstractRoutingDataSource抽象类源码
关注import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource以下变量
@Nullable
private Map targetDataSources; // 目标数据源
@Nullable
private Object defaultTargetDataSource; // 默认目标数据源
@Nullable
private Map resolvedDataSources; // 解析的数据源
@Nullable
private DataSource resolvedDefaultDataSource; // 解析的默认数据源
这两组变量是相互对应的,在熟悉多实例数据源切换代码的不难发现,当有多个数据源的时候,一定要指定一个作为默认的数据源;
在这里也同理,当同时初始化多个数据源的时候,需要显式的调用setDefaultTargetDataSource方法指定一个作为默认数据源;
我们需要关注的是Map targetDataSources和Map resolvedDataSources;
targetDataSources是暴露给外部程序用来赋值的,而resolvedDataSources是程序内部执行时的依据,因此会有一个赋值的操作;
根据这段源码可以看出,每次执行时,都会遍历targetDataSources内的所有元素并赋值给resolvedDataSources;这样如果我们在外部程序新增一个新的数据源,都会添加到内部使用,从而实现数据源的动态加载。
继承该抽象类的时候,必须实现一个抽象方法:protected abstract Object determineCurrentLookupKey(),该方法用于指定到底需要使用哪一个数据源。
二、实现多数据源切换和动态数据源加载
A - 配置文件信息
application.yml文件
server:
port: 18080
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
# 主数据源
master-db:
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.223.129:13306/test_master_db?characterEncoding=utf-8
username: josen
password: josen
# 从数据源
slave-db:
driverClassName: com.mysql.jdbc.Driver
url: 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:
com.josen.mydemo20201105: 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
org.mybatis.spring.boot
mybatis-spring-boot-starter
2.1.3
mysql
mysql-connector-jav