欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

springboot多數(shù)據(jù)源使用@Qualifier自動(dòng)注入無效的解決

 更新時(shí)間:2021年11月18日 09:02:41   作者:霂宇  
這篇文章主要介紹了springboot多數(shù)據(jù)源使用@Qualifier自動(dòng)注入無效的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。也希望大家多多支持腳本之家

@Qualifier自動(dòng)注入無效的解決

問題

使用springboot進(jìn)行多數(shù)據(jù)源時(shí),發(fā)生了單例DataSource對(duì)應(yīng)多個(gè)DataSourceBean的問題。

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

問題的根本原因

主要在于SpringBoot的DataSourceInitializer,該類在autoConfigure包中,用來自動(dòng)初始化一個(gè)內(nèi)置的DataSource實(shí)例,在創(chuàng)建該實(shí)例的時(shí)候發(fā)生了注入的問題。

創(chuàng)建實(shí)例的流程(記錄一下方便以后再次調(diào)試):

1. 調(diào)用DataSourceInitializer的構(gòu)造方法

2. 調(diào)用AbstractAutowireCapableBeanFactory的applyMergedBeanDefinitionPostProcessors方法

3. 調(diào)用AbstractAutowireCapableBeanFactory的initializeBean方法

4. AbstractAutowireCapableBeanFactory的applyBeanPostProcessorsBeforeInitialization方法,其中有一個(gè)循環(huán)是用多種Bean處理器來處理DataSourceInitializer對(duì)象

5. 之后使用反射的方式跳轉(zhuǎn)到DataSourceInitializer的init方法

6.里面通過this.applicationContext.getBean(DataSource.class)來獲取所有DataSource的實(shí)現(xiàn)類對(duì)象實(shí)例。

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

8. 如果對(duì)象實(shí)例的實(shí)例數(shù)量大于1,則會(huì)進(jìn)入以下的兩個(gè)判斷:

判斷是否有Primary的實(shí)例,或者是優(yōu)先級(jí)高的實(shí)例對(duì)象,如果有,則將候選對(duì)象名賦值給candidateName。沒有則置為空,最后拋出多個(gè)實(shí)例的異常。

其中問題出在

因?yàn)轫?xiàng)目中只使用了@Qualifier,而且springboot的DataSourceInitializer沒有對(duì)@Qualifier的處理,所以沒有對(duì)實(shí)例進(jìn)行匹配。

造成多個(gè)數(shù)據(jù)源實(shí)例。對(duì)于存在多數(shù)據(jù)源的情況,他們做的補(bǔ)救措施是在代碼中添加了是否是Primary和是否是HighestPriority的判斷,

來處理采用哪個(gè)數(shù)據(jù)源。所以解決的方式也因此出來了。就是將某個(gè)實(shí)例標(biāo)記為Primary或者HighestPriority。

解決問題的方法

在某個(gè)@Bean上添加@Primary注解,就可以做到唯一區(qū)分。

這里其實(shí)應(yīng)該還可以通過優(yōu)先級(jí)來區(qū)分,但使用@Order發(fā)現(xiàn)并不是這個(gè)優(yōu)先級(jí),也沒找到相關(guān)的資料,所以之后再研究一下。

@Qualifier的作用和應(yīng)用

@Qualifier的作用

這是官方的介紹

This annotation may be used on a field or parameter as a qualifier for candidate beans when autowiring. It may also be used to annotate other custom annotations that can then in turn be used as qualifiers.

簡單的理解就是:

  • 在使用@Autowire自動(dòng)注入的時(shí)候,加上@Qualifier(“test”)可以指定注入哪個(gè)對(duì)象;
  • 可以作為篩選的限定符,我們?cè)谧鲎远x注解時(shí)可以在其定義上增加@Qualifier,用來篩選需要的對(duì)象。這個(gè)理解看下面的代碼吧,不好解釋。

功能介紹

首先是對(duì)(1)的理解。

//我們定義了兩個(gè)TestClass對(duì)象,分別是testClass1和testClass2
//我們?nèi)绻诹硗庖粋€(gè)對(duì)象中直接使用@Autowire去注入的話,spring肯定不知道使用哪個(gè)對(duì)象
//會(huì)排除異常 required a single bean, but 2 were found
@Configuration
public class TestConfiguration {
   @Bean("testClass1")
   TestClass testClass1(){
       return new TestClass("TestClass1");
   }
   @Bean("testClass2")
   TestClass testClass2(){
       return new TestClass("TestClass2");
   }
}

下面是正常的引用

@RestController
public class TestController {
 
    //此時(shí)這兩個(gè)注解的連用就類似 @Resource(name="testClass1")
    @Autowired
    @Qualifier("testClass1")
    private TestClass testClass;
 
    @GetMapping("/test")
    public Object test(){
        return testClassList;
    }

}

@Autowired和@Qualifier這兩個(gè)注解的連用在這個(gè)位置就類似 @Resource(name=“testClass1”)

對(duì)(2)的理解

@Configuration
public class TestConfiguration {
    //我們調(diào)整下在testClass1上增加@Qualifier注解
    @Qualifier
    @Bean("testClass1")
    TestClass testClass1(){
        return new TestClass("TestClass1");
    }
 
    @Bean("testClass2")
    TestClass testClass2(){
        return new TestClass("TestClass2");
    }
}
@RestController
public class TestController {
    //我們這里使用一個(gè)list去接收testClass的對(duì)象
    @Autowired
    List<TestClass> testClassList= Collections.emptyList();
    
    @GetMapping("/test")
    public Object test(){
        return testClassList;
    }
}

我們調(diào)用得到的結(jié)果是

[
{
"name": "TestClass1"
},
{
"name": "TestClass2"
}
]

我們可以看到所有的testclass都獲取到了。接下來我們修改下代碼

@RestController
public class TestController {
 
    @Qualifier //我們?cè)谶@增加注解
    @Autowired
    List<TestClass> testClassList= Collections.emptyList();
 
    @GetMapping("/test")
    public Object test(){
        return testClassList;
    }
}

和上面代碼對(duì)比就是在接收參數(shù)上增加了@Qualifier注解,這樣看是有什么區(qū)別,我們調(diào)用下,結(jié)果如下:

[
{
"name": "TestClass1"
}
]

返回結(jié)果只剩下增加了@Qualifier注解的TestClass對(duì)象,這樣我們就可以理解官方說的標(biāo)記篩選是什么意思了。

另外,@Qualifier注解是可以指定value的,這樣我們可以通過values來分類篩選想要的對(duì)象了,這里不列舉代碼了,感興趣的同學(xué)自己試試。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Maven最佳實(shí)踐之一個(gè)好的parent依賴基礎(chǔ)

    Maven最佳實(shí)踐之一個(gè)好的parent依賴基礎(chǔ)

    今天小編就為大家分享一篇關(guān)于Maven最佳實(shí)踐之一個(gè)好的parent依賴基礎(chǔ),小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2018-12-12
  • Java?事務(wù)注解@Transactional回滾(try?catch、嵌套)問題

    Java?事務(wù)注解@Transactional回滾(try?catch、嵌套)問題

    這篇文章主要介紹了Java?@Transactional回滾(try?catch、嵌套)問題,Spring?事務(wù)注解?@Transactional?本來可以保證原子性,如果事務(wù)內(nèi)有報(bào)錯(cuò)的話,整個(gè)事務(wù)可以保證回滾,但是加上try?catch或者事務(wù)嵌套,可能會(huì)導(dǎo)致事務(wù)回滾失敗
    2022-08-08
  • Java中讓界面內(nèi)的時(shí)間及時(shí)更新示例代碼

    Java中讓界面內(nèi)的時(shí)間及時(shí)更新示例代碼

    這篇文章主要給大家介紹了關(guān)于Java中讓界面內(nèi)的時(shí)間及時(shí)更新的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • Java實(shí)戰(zhàn)之基于swing的QQ郵件收發(fā)功能實(shí)現(xiàn)

    Java實(shí)戰(zhàn)之基于swing的QQ郵件收發(fā)功能實(shí)現(xiàn)

    這篇文章主要介紹了Java實(shí)戰(zhàn)之基于swing的QQ郵件收發(fā)功能實(shí)現(xiàn),文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-04-04
  • SpringBoot2整合ElasticJob框架過程詳解

    SpringBoot2整合ElasticJob框架過程詳解

    這篇文章主要介紹了SpringBoot2整合ElasticJob框架過程詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-03-03
  • Java簡單幾步實(shí)現(xiàn)一個(gè)二叉搜索樹

    Java簡單幾步實(shí)現(xiàn)一個(gè)二叉搜索樹

    二叉樹包含了根節(jié)點(diǎn),孩子節(jié)點(diǎn),葉節(jié)點(diǎn),每一個(gè)二叉樹只有一個(gè)根節(jié)點(diǎn),每一個(gè)結(jié)點(diǎn)最多只有兩個(gè)節(jié)點(diǎn),左子樹的鍵值小于根的鍵值,右子樹的鍵值大于根的鍵值,下面這篇文章主要給大家介紹了關(guān)于如何在Java中實(shí)現(xiàn)二叉搜索樹的相關(guān)資料,需要的朋友可以參考下
    2023-02-02
  • JAVA+Struts2獲取服務(wù)器地址的方法

    JAVA+Struts2獲取服務(wù)器地址的方法

    這篇文章主要介紹了JAVA+Struts2獲取服務(wù)器地址的方法,是Struts2的一個(gè)簡單應(yīng)用,具有一定的借鑒與參考價(jià)值,需要的朋友可以參考下
    2014-11-11
  • JAVA獲取rabbitmq消息總數(shù)過程詳解

    JAVA獲取rabbitmq消息總數(shù)過程詳解

    這篇文章主要介紹了JAVA獲取rabbitmq消息總數(shù)過程詳解,公司使用的是rabbitMQ,需要做監(jiān)控預(yù)警的job去監(jiān)控rabbitMQ里面的堆積消息個(gè)數(shù),如何使用rabbitMQ獲取監(jiān)控的隊(duì)列里面的隊(duì)列消息個(gè)數(shù)呢,需要的朋友可以參考下
    2019-07-07
  • Springboot線程池并發(fā)處理數(shù)據(jù)優(yōu)化方式

    Springboot線程池并發(fā)處理數(shù)據(jù)優(yōu)化方式

    這篇文章主要介紹了Springboot線程池并發(fā)處理數(shù)據(jù)優(yōu)化方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • maven依賴傳遞和依賴沖突原理

    maven依賴傳遞和依賴沖突原理

    這篇文章主要介紹了maven依賴傳遞和依賴沖突原理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05

最新評(píng)論