springboot多數據源使用@Qualifier自動注入無效問題

問題:

          使用springboot進行多數據源時,發生了單例DataSource對應多個DataSourceBean的問題。

          具體錯誤如下:XXXXX required a single bean, but 3 were found。通過@Qualifier來區分,或是在@Bean中添加name屬性來區分,都沒有作用。

 

問題的根本原因:

          主要在於SpringBoot的DataSourceInitializer,該類在autoConfigure包中,用來自動初始化一個內置的DataSource實例,在創建該實例的時候發生了注入的問題。

          創建實例的流程(記錄一下方便以後再次調試):

                    1. 調用DataSourceInitializer的構造方法

                    2. 調用AbstractAutowireCapableBeanFactory的applyMergedBeanDefinitionPostProcessors方法

                    3. 調用AbstractAutowireCapableBeanFactory的initializeBean方法

                    4. AbstractAutowireCapableBeanFactory的applyBeanPostProcessorsBeforeInitialization方法,其中有一個循環是用多種Bean處理器來處理DataSourceInitializer對象

                    5. 之後使用反射的方式跳轉到DataSourceInitializer的init方法

                    6.裏面通過this.applicationContext.getBean(DataSource.class)來獲取所有DataSource的實現類對象實例。

                    7. DefaultListableBeanFactory的resolveNamedBean方法中來選取實例對象,通過裏面的getBeanNamesForType方法獲取到所有的符合requireType(也就是DataSource.class)的對象。

                    8. 如果對象實例的實例數量大於1,則會進入以下的兩個判斷:

                    

                    判斷是否有Primary的實例,或者是優先級高的實例對象,如果有,則將候選對象名賦值給candidateName。沒有則置爲空,最後拋出多個實例的異常。

 

其中問題出在:

          因爲項目中只使用了@Qualifier,而且springboot的DataSourceInitializer沒有對@Qualifier的處理,所以沒有對實例進行匹配。

          造成多個數據源實例。對於存在多數據源的情況,他們做的補救措施是在代碼中添加了是否是Primary和是否是HighestPriority的判斷,

          來處理採用哪個數據源。所以解決的方式也因此出來了。就是將某個實例標記爲Primary或者HighestPriority。

 

解決問題的方法:

         在某個@Bean上添加@Primary註解,就可以做到唯一區分。

          這裏其實應該還可以通過優先級來區分,但使用@Order發現並不是這個優先級,也沒找到相關的資料,所以之後再研究一下。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章