大家好,我是此林。
SpringBoot 手動實現動態切換數據源 DynamicSource (上)-CSDN博客
在上一篇博客中,我帶大家手動實現了一個簡易版的數據源切換實現,方便大家理解數據源切換的原理。今天我們來介紹一個開源的數據源切換框架,是baomidou 旗下和 Mybatis-plus 同級的開源框架:dynamic-datasource-spring-boot-starter。
1. 簡介
dynamic-datasource-spring-boot-starter 是一個基于springboot的快速集成多數據源的啟動器。
其支持?Jdk 1.7+, SpringBoot 1.5.x 2.x.x 3.x.x。
JPA用戶不建議使用,JPA自帶事務,無法連續切庫。
2. 使用
下面基于SpringBoot2 做演示。
1.pom.xml
<dependency><groupId>com.baomidou</groupId><artifactId>dynamic-datasource-spring-boot-starter</artifactId><version>4.3.1</version>
</dependency>
2.application.yml
spring:datasource:dynamic:primary: master #設置默認的數據源或者數據源組,默認值即為masterstrict: false #嚴格匹配數據源,默認false. true未匹配到指定數據源時拋異常,false使用默認數據源datasource:master:url: jdbc:mysql://192.168.183.128:3306/userusername: rootpassword: 123456slave_1:url: jdbc:mysql://192.168.183.128:3307/userusername: rootpassword: 123456slave_2:url: jdbc:mysql://192.168.183.128:3308/userusername: rootpassword: 123456
參數說明:
以上會配置一個默認庫master,一個組slave下有兩個子庫slave_1,slave_2
后續我們會使用AOP注解的方式指定數據源。
例如:@DS("master")、@DS("slave")
- 配置文件所有以下劃線?
_
?分割的數據源?首部?即為組的名稱,相同組名稱的數據源會放在一個組下。 - 切換數據源可以是組名,也可以是具體數據源名稱。組名則切換時采用負載均衡算法切換。
例如:當我們使用@DS("slave")時,指定了組名? “slave”,那么它會采用負載均衡算法自動切換數據源。
因為我們后續希望實現Mysql主從讀寫分離,所有寫操作走master數據庫,所有讀操作走slave從數據庫。
3.?使用?@DS?切換數據源。
@Service
public class UserServiceImpl implements UserService {@Autowiredprivate UserMapper userMapper;@Overridepublic void insert(User user) {userMapper.insert(user);}@Override@DS("slave_1")public List<User> selectAll() {userMapper.selectAll();}@Override@DS("slave")public User selectById(Integer id) {return userMapper.selectById(id);}
}
說明:
insert() 方法沒有加@DS,默認使用master數據庫。
selectAll() 方法指定使用數據源slave_1
selectById() 使用slave組,自動負載均衡查詢。
注:@DS?可以注解在方法上或類上,同時存在就近原則 方法上注解 優先于 類上注解。
若要實現Mysql主從自動復制,還需要配置mysql主從復制,詳情參考博客:
ShardingSphere5:Mysql主從集群搭建、讀寫分離_shardingsphere mysql讀寫分離-CSDN博客
其中SpringBoot配置 ShardingSphere5 這一塊不用管,Mysql主從集群搭建是不變的。
4.其他實現
3. 底層原理
1. SpringBoot自動配置
我們找到?DynamicDataSourceAutoConfiguration.class。 這是框架的自動配置類。
這一段是從我們配置的application.yml 讀取并設置相關屬性,也就是我們配置的數據源信息。
具體的話,是賦值給 DynamicRoutingDataSource 這個對象。
2. 掃描@DS注解
這是?DynamicDataSourceAnnotationInterceptor 的 invoke 方法,典型的AOP。
在所有加了@DS的方法上,
1. 當執行目標方法的時候,會先獲取到@DS("XXX")中數據源的名稱,dsKey。
2. 然后再把dsKey 存到ThreadLocal中,也就是圖中的DynamicDataSourceContextHolder。
3. 最后再開始執行目標方法。
3.?DynamicRoutingDataSource
回到我們之前自動配置里說的 DynamicRoutingDataSource
觀察?DynamicRoutingDataSource 的繼承關系鏈,發現它實現了Spring的 DataSource 和 InitializingBean 接口。
這和我們上一篇博客手動實現數據源切換的思路是一樣的。
在?DynamicRoutingDataSource 里,determineDataSource 從 ThreadLocal 里 獲取到指定數據源名稱
最后通過名稱返回對應的DataSource數據源。
對比上一篇博客,
SpringBoot 手動實現動態切換數據源 DynamicSource (上)-CSDN博客
其實思路大差不差,只不過?dynamic-datasource-spring-boot-starter 更加完善,增加了AOP注解功能。
4. 無注解切換數據源
1. 自定義切面,結合?DynamicDatasourceNamedInterceptor ,對于所有以 select 方法開頭的,設置使用 slave 數據源,?對于add、update、delete 開頭的使用 master 數據源。
2. 自定義 Mybatis 攔截器,對于所有的寫操作使用 master?數據源,所有讀操作使用 slave 數據源。(即:把數據源標識寫入?DynamicDataSourceContextHolder 中)。
3. 其他場景:SaaS多租戶系統下,每個租戶使用獨立的數據庫,那么可以要求前端攜帶請求頭 “dsKey”。配置自定義攔截器,攔截請求,把dsKey 寫入?DynamicDataSourceContextHolder。
今天的分享就到這里。
我是此林,關注我吧,帶你看不一樣的世界!