在项目涉及到多个库的操作时,那么就要设置多个数据源,此时就涉及到数据源的动态切换问题。
本文提供一种通过使用 AbstractRoutingDataSource 结合AOP 实现通过注解动态切换数据源的思路与大致实现,并给出一个Demo。
大致步骤
- 什么是 AbstractRoutingDataSource
- application.yaml 添加数据源配置信息
- 数据源相关配置类
- 数据源属性配置类 DruidProperties
- 自定义数据源注解 @DataSource
- 保存数据源名称工具类 DynamicDataSourceContextHolder
- 动态数据源类继承 AbstractRoutingDataSource
- AOP切面类
- 源码地址
0. 什么是 AbstractRoutingDataSource
Abstract DataSource implementation that routes getConnection() calls to one of various target DataSources based on a lookup key. The latter is usually (but not necessarily) determined through some thread-bound transaction context.
源码上的注解大致意思是:AbstractRoutingDataSource 是抽象 DataSource 的实现, 其 getConnection() 方法根据 lookupKey 键去调用不同的目标数据源。数据源通常(但不一定)是通过某些线程绑定事务上下文去确定。
也就是说实现了这个spring提供的抽象类,就可以在程序运行的时候,根据自定义的规则动态切换数据源。
重写该类提供的抽象方法determineCurrentLookupKey
,提供不同的 lookKey 就可以实现当时使用哪个数据源。
1. application.yaml 添加数据源配置信息
首先需要在application.yaml添加数据源的配置信息,可以按照自己的需要配置多个。
这里只配置了两个数据源的主要信息,一个主数据源和一个从数据源。
# 数据源配置
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
ds:
# 主数据源
master:
url: jdbc:mysql://localhost:3306/test09?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: ***
# 从数据源
slave:
url: jdbc:mysql://localhost:3306/test08?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: ***
2. 数据源相关配置类
1. 数据源属性配置类 DruidProperties
@ConfigurationProperties(prefix = "spring.datasource")
public class DruidProperties {
private String type;
private String driverClassName;
private Map<String, Map<String, String>> ds;
/**
* 通过外部构造 DruidDataSource 对象
*/
public DataSource dataSource(DruidDataSource druidDataSource) {
return druidDataSource;
}
//...getter和setter略
}
我们选择了在外部构造 DataSource对象,还需要一个类加载所有的数据源。
@Com