org.springframeword.boot:spring-boot-starer-web: 2.0.4release
io.shardingsphere:sharding-jdbc-spring-boot-starter:3.0.0M3
org.mybatis.spring.boot:mybatis-spring-boot-starter:1.3.1
com.alibaba:druid-spring-boot-starter:1.1.9
由於項目需要,走了一波sharding jdbc多數據源配置,算是實戰演練了,此處記錄下踩過的坑。
代碼githut地址(https://github.com/autLory/test_sharding_pro),閹割版,去掉了與項目相關的東西,剩一些核心配置文件。
1,初始版本參考網上找各路大佬的博客資料寫出來的,配置了兩個數據源,然后在DataSourceConfig里面分別初始化,基本實現分庫分表,主庫的分表策略在配置文件里面配置,分庫的分表策略是在DataSourceConfig文件里面初始化的時候配置手動寫ShardingRuleConfiguration然后加到ShardingDataSource里面的(其實好一些的處理方法應該是都寫在配置文件里面的,但是我沒做出來)。兩個DataSourceConfig文件分別初始化自己的數據源,mapper,xmlmapper,基本就完成了最初的版本。啟動時的時候去除掉Spring boot自帶的DataSourceAutoConfiguration文件。
2,初始版本完成之后,發現的第一個問題就是以前項目里面寫的一個mybatis的攔截器失效了,攔截器的作用是攔截mybatis所有的insert ,update操作,添加一些業務字段,沒改多數據源之前是正常使用的,改了之后發現失效了,然后debug模式啟動發現攔截器確實是已經初始化過了,至於為什么沒有生效,不知道。
解決思路:看源碼了,先找到前面去除掉的DataSourceAutoConfiguration文件,看看源碼,好像跟mybatis沒什么關系,然后搜了下spring boot自動配置mybatis的初始化過程找到了MybatisAutoConfiguration文件,也就是mybatis的初始化配置文件,,AutoConfigAfter,字面理解執行於參數的class文件初始化之后,這個類里面有個構造函數如下
看起來好像找到一個跟攔截器有點關系的了,然后看看下面哪個地方被調用,如下:
在初始化SqlSessionFactory的時候會把攔截器添加到實例里面,對比自己的Config文件,少了這么一步,所以攔截器初始化了但是沒有生效時因為沒有添加到mybatis的實例里面。
對應的改一下自己的配置文件,把interceptor加進去,再啟動測試,正常使用,搞定。
3 ,后續發現的第二個問題,druid的sql監控沒有了。為啥沒有了,不知道,繼續找原因改唄。
第一個猜測,druid相關的配置沒有生效, 又開始debug配置文件,發現了一個問題
此處DataSource初始化是直接調用DataSourceBuilder的.build方法初始化的,沒有任何參數,好吧,再看看DataSourceBuilder的代碼
這個地方會去獲取DataSource的類型,然后結果拿到的就是HikariDataSource,鬼鬼,怪不得沒sql監控了,初始化出來的DataSource壓根就不是DruidDataSource,原因找到了,繼續改了,怎么改了,先看sharding初始化DataSource的源碼,實際上Sharding jdbc的DataSource初始化是根據配置文件里面type屬性來的,代碼在SpringBootConfiguration文件
這個地方在初始化DataSourceMap的時候會找到配置文件里面 sharding.jdbc.datasource.names值對應的數據源,然后配置對應屬性
看代碼會發現這給放主要會調用兩個方法
一個是public static <T> T handle(final Environment environment, final String prefix, final Class<T> targetClass)方法
該方法作用是將當前environment下的配置文件里面前綴為prefix的屬性轉換為一個targetClass對象
代碼里面就是將前面為sharding.jdbc.datasource.ds的屬性轉換為一個map對象
第二個方法為DataSource getDataSource(final String dataSourceClassName, final Map<String, Object> dataSourceProperties)
源碼如下,
意思是先找到DataSource類型的class對象,然后循環前面獲取到的map對象,利用反射找到每一個key對應的set方法,將value值作為set方法的參數賦值給實例化出來的對象,然后將這個對象返回給上層的DataSouce初始化方法。這就實現了根據配置文件類實例化不同類型的DataSource實例。
而實際上我這邊是有問題的,項目確認使用druid連接池,所以我沒有把這些方法都copy到自己代碼里面,而是在自己的DataSourceConfig文件里面直接初始化一個DruidDataSource實例返回,初始化的時候直接讀取配置文件的各個屬性值賦值。改好之后再次啟動測試,就可以正常啟動druid的sql監控了。
以上!