亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

@Qualifier使用及詳細(xì)源碼展示

 更新時(shí)間:2025年09月04日 09:44:44   作者:csdn_tom_168  
@Qualifier是Spring解決依賴注入歧義的注解,通過(guò)限定符名稱指定具體Bean,與@Primary不同,可覆蓋主Bean,適用于多實(shí)現(xiàn)類和自定義限定符場(chǎng)景,需注意大小寫(xiě)敏感及字段注入的耦合問(wèn)題,配合@Autowired提升靈活性

@Qualifier 是 Spring 框架中用于解決依賴注入歧義的核心注解,當(dāng)容器中存在多個(gè)同類型 Bean 時(shí),通過(guò)它可以顯式指定要注入的具體 Bean。

以下從注解定義、源碼解析、核心功能、使用場(chǎng)景注意事項(xiàng)展開(kāi)詳細(xì)說(shuō)明,幫助理解其在依賴注入中的關(guān)鍵作用。

一、@Qualifier注解的定義與源碼解析

@Qualifier 位于 org.springframework.beans.factory.annotation 包中,其源碼定義如下(簡(jiǎn)化版):

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Qualifier {

    /**
     * 限定符名稱(用于匹配 Bean 的名稱或自定義限定符)
     */
    String value() default "";
}

關(guān)鍵屬性說(shuō)明

  • value:必填屬性,指定限定符名稱。該名稱可以是 Bean 的名稱(默認(rèn)通過(guò) @Component@Beanvalue 屬性定義),也可以是自定義的限定符(需通過(guò) @Qualifier@Beanvalue 顯式聲明)。

二、核心功能:解決多候選 Bean 的歧義

在 Spring 中,當(dāng)一個(gè)接口有多個(gè)實(shí)現(xiàn)類(或一個(gè)類被多次聲明為 Bean)時(shí),直接使用 @Autowired 注入會(huì)因“找不到唯一匹配的 Bean”而拋出 NoUniqueBeanDefinitionException。

@Qualifier 的核心作用是通過(guò)限定符名稱明確指定要注入的 Bean,消除歧義。

1.工作流程

Spring 處理 @Qualifier 的流程與 @Autowired 緊密協(xié)作,核心步驟如下:

  1. 依賴類型匹配@Autowired 首先根據(jù)字段/方法參數(shù)的類型,從容器中查找所有匹配類型的 Bean(稱為“候選 Bean”)。
  2. 限定符匹配:若存在多個(gè)候選 Bean,@Qualifiervalue 屬性會(huì)被用來(lái)篩選出名稱或限定符完全匹配的 Bean。
  3. 注入目標(biāo) Bean:將篩選出的唯一 Bean 注入到目標(biāo)位置。

2.與@Primary的區(qū)別

  • @Primary:標(biāo)記一個(gè) Bean 為“主候選”,當(dāng)存在多個(gè)同類型 Bean 時(shí),優(yōu)先選擇被 @Primary 標(biāo)記的 Bean(無(wú)需顯式 @Qualifier)。
  • @Qualifier:顯式指定要注入的 Bean 名稱或限定符,優(yōu)先級(jí)高于 @Primary(即使存在 @Primary Bean,@Qualifier 仍可選擇其他 Bean)。

三、典型使用場(chǎng)景與示例

1.多個(gè)同類型 Bean 的注入

當(dāng)一個(gè)接口有多個(gè)實(shí)現(xiàn)類時(shí)(如 PaymentServiceAlipayServiceWechatPayService 兩個(gè)實(shí)現(xiàn)),使用 @Qualifier 指定具體實(shí)現(xiàn):

步驟 1:定義接口與實(shí)現(xiàn)類

public interface PaymentService {
    void pay(Double amount);
}

@Service("alipayService") // 指定 Bean 名稱為 "alipayService"
public class AlipayService implements PaymentService {
    @Override
    public void pay(Double amount) {
        System.out.println("支付寶支付:" + amount);
    }
}

@Service("wechatPayService") // 指定 Bean 名稱為 "wechatPayService"
public class WechatPayService implements PaymentService {
    @Override
    public void pay(Double amount) {
        System.out.println("微信支付:" + amount);
    }
}

步驟 2:使用 @Qualifier 注入指定 Bean

@Service
public class OrderService {

    private final PaymentService paymentService;

    // 通過(guò) @Qualifier 指定注入 "alipayService"
    @Autowired
    public OrderService(@Qualifier("alipayService") PaymentService paymentService) {
        this.paymentService = paymentService;
    }

    public void createOrder(Double amount) {
        paymentService.pay(amount); // 輸出:支付寶支付:100.0
    }
}

2.自定義限定符(非 Bean 名稱)

若需要更靈活的限定(如按業(yè)務(wù)場(chǎng)景區(qū)分),可通過(guò) @Qualifier 自定義限定符名稱(無(wú)需與 Bean 名稱一致):

步驟 1:定義自定義限定符

通過(guò) @Qualifier 注解標(biāo)記一個(gè)自定義限定符(或直接在 @Bean 中指定 value):

// 方式 1:通過(guò) @Qualifier 注解標(biāo)記(需配合 @Bean)
@Qualifier("domesticPay") // 自定義限定符名稱
@Service
public class DomesticPaymentService implements PaymentService {
    @Override
    public void pay(Double amount) {
        System.out.println("國(guó)內(nèi)支付:" + amount);
    }
}

// 方式 2:在 @Bean 中直接指定 value(更常見(jiàn))
@Configuration
public class PaymentConfig {

    @Bean("overseasPay") // 自定義限定符名稱
    public PaymentService overseasPaymentService() {
        return new PaymentService() {
            @Override
            public void pay(Double amount) {
                System.out.println("海外支付:" + amount);
            }
        };
    }
}

步驟 2:使用自定義限定符注入

@Service
public class InternationalOrderService {

    private final PaymentService overseasPaymentService;

    @Autowired
    public InternationalOrderService(@Qualifier("overseasPay") PaymentService paymentService) {
        this.overseasPaymentService = paymentService;
    }

    public void createInternationalOrder(Double amount) {
        overseasPaymentService.pay(amount); // 輸出:海外支付:200.0
    }
}

3.與@Autowired(required = false)配合使用

當(dāng)依賴可能不存在時(shí),@Qualifier 可與 required = false 配合,避免啟動(dòng)失?。?/p>

@Service
public class OptionalPaymentService {

    private final PaymentService optionalPaymentService;

    // required = false,無(wú)匹配 Bean 時(shí)注入 null
    @Autowired(required = false)
    public OptionalPaymentService(@Qualifier("optionalPay") PaymentService optionalPaymentService) {
        this.optionalPaymentService = optionalPaymentService;
    }

    public void optionalPay(Double amount) {
        if (optionalPaymentService != null) {
            optionalPaymentService.pay(amount);
        } else {
            System.out.println("無(wú)可用支付服務(wù)");
        }
    }
}

四、源碼實(shí)現(xiàn)細(xì)節(jié)與關(guān)鍵類

1.QualifierAnnotationAutowireCandidateResolver

Spring 處理 @Qualifier 的核心類,負(fù)責(zé)解析 @Qualifier 注解并匹配候選 Bean。其主要方法包括:

  • isAutowireCandidate:判斷一個(gè) Bean 是否是當(dāng)前依賴的候選(考慮 @Qualifier 限定符)。

2.AutowiredAnnotationBeanPostProcessor

postProcessProperties 方法中,通過(guò) QualifierAnnotationAutowireCandidateResolver 解析 @Qualifier 注解,篩選出匹配的 Bean 并注入。

3.BeanFactory的getBean方法

底層通過(guò) BeanFactory.getBean(Qualifier, Class) 方法,根據(jù)限定符名稱查找匹配的 Bean。

五、注意事項(xiàng)與常見(jiàn)問(wèn)題

1.限定符名稱的大小寫(xiě)敏感

@Qualifiervalue 屬性是大小寫(xiě)敏感的,需與 Bean 的名稱或自定義限定符完全一致(如 alipayServiceAlipayService 會(huì)被視為不同)。

2.避免濫用字段注入

雖然 @Qualifier 可以解決字段注入的歧義問(wèn)題,但字段注入仍存在類與容器緊耦合的問(wèn)題。推薦使用構(gòu)造器注入,強(qiáng)制依賴在對(duì)象創(chuàng)建時(shí)完成注入,提高可測(cè)試性。

3.與@Resource的區(qū)別

特性@Qualifier + @Autowired@Resource
來(lái)源Spring 自定義注解JSR-250 標(biāo)準(zhǔn)注解(Java EE)
匹配順序優(yōu)先按類型,其次按 @Qualifier 名稱優(yōu)先按名稱,其次按類型
多候選處理必須顯式使用 @Qualifier 消除歧義自動(dòng)選擇第一個(gè)匹配的 Bean(可能歧義)

4.自定義限定符的擴(kuò)展

可通過(guò)實(shí)現(xiàn) org.springframework.beans.factory.annotation.Qualifier 接口(或使用 @Qualifier 注解)定義更復(fù)雜的限定符邏輯(如按屬性值匹配),但通常直接使用 value 屬性指定名稱已足夠。

5.性能優(yōu)化

  • 避免在 @Qualifier 中使用復(fù)雜的名稱匹配(如通配符),可能導(dǎo)致額外的查找開(kāi)銷。
  • 對(duì)于高頻使用的限定符,可通過(guò) @Primary@Beanvalue 預(yù)先標(biāo)記,減少運(yùn)行時(shí)匹配成本。

六、總結(jié)

@Qualifier 是 Spring 解決依賴注入歧義的核心工具,通過(guò)顯式指定限定符名稱或 Bean 名稱,確保在多個(gè)同類型 Bean 中準(zhǔn)確注入目標(biāo) Bean。

其核心機(jī)制依賴 QualifierAnnotationAutowireCandidateResolverAutowiredAnnotationBeanPostProcessor 的協(xié)作,支持與 @Autowired、@Primary 等注解的靈活配合。

理解其源碼和使用場(chǎng)景,有助于開(kāi)發(fā)者編寫(xiě)更健壯、可維護(hù)的 Spring 應(yīng)用。

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

相關(guān)文章

  • Spring AI內(nèi)置DeepSeek的詳細(xì)步驟

    Spring AI內(nèi)置DeepSeek的詳細(xì)步驟

    Spring AI 最新快照版已經(jīng)內(nèi)置 DeepSeek 了,所以以后項(xiàng)目中對(duì)接 DeepSeek 就方便多了,但因?yàn)榭煺瞻鏁?huì)有很多 Bug,所以今天咱們就來(lái)看穩(wěn)定版的 Spring AI 如何對(duì)接 DeepSeek 滿血版,感興趣的小伙伴跟著小編一起來(lái)看看吧
    2025-02-02
  • feign調(diào)用中文參數(shù)被encode編譯的問(wèn)題

    feign調(diào)用中文參數(shù)被encode編譯的問(wèn)題

    這篇文章主要介紹了feign調(diào)用中文參數(shù)被encode編譯的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • 基于SpringBoot+vue實(shí)現(xiàn)前后端數(shù)據(jù)加解密

    基于SpringBoot+vue實(shí)現(xiàn)前后端數(shù)據(jù)加解密

    這篇文章主要給大家介紹了基于SpringBoot+vue實(shí)現(xiàn)前后端數(shù)據(jù)加解密,文中有詳細(xì)的示例代碼,具有一定的參考價(jià)值,感興趣的小伙伴可以自己動(dòng)手試一試
    2023-08-08
  • java多線程批量拆分List導(dǎo)入數(shù)據(jù)庫(kù)的實(shí)現(xiàn)過(guò)程

    java多線程批量拆分List導(dǎo)入數(shù)據(jù)庫(kù)的實(shí)現(xiàn)過(guò)程

    這篇文章主要給大家介紹了關(guān)于java多線程批量拆分List導(dǎo)入數(shù)據(jù)庫(kù)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2021-10-10
  • java通過(guò)Idea遠(yuǎn)程一鍵部署springboot到Docker詳解

    java通過(guò)Idea遠(yuǎn)程一鍵部署springboot到Docker詳解

    這篇文章主要介紹了java通過(guò)Idea遠(yuǎn)程一鍵部署springboot到Docker詳解,Idea是Java開(kāi)發(fā)利器,springboot是Java生態(tài)中最流行的微服務(wù)框架,docker是時(shí)下最火的容器技術(shù),那么它們結(jié)合在一起會(huì)產(chǎn)生什么化學(xué)反應(yīng)呢?的相關(guān)資料
    2019-06-06
  • 淺析java中常用的定時(shí)任務(wù)框架-單體

    淺析java中常用的定時(shí)任務(wù)框架-單體

    這篇文章主要帶大家了解常用的單體應(yīng)用定時(shí)任務(wù)框架以及掌握定時(shí)任務(wù)在單體中如何使用,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2021-12-12
  • 詳解Java中的hashcode

    詳解Java中的hashcode

    這篇文章主要介紹了詳解Java中的hashcode,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-05-05
  • java 字浮串提取方法匯集

    java 字浮串提取方法匯集

    用方法toCharArray public char[] toCharArray()
    2008-10-10
  • SpringBoot+MyBatis-Plus實(shí)現(xiàn)分頁(yè)的項(xiàng)目實(shí)踐

    SpringBoot+MyBatis-Plus實(shí)現(xiàn)分頁(yè)的項(xiàng)目實(shí)踐

    MyBatis-Plus是基于MyBatis的持久層增強(qiáng)工具,提供簡(jiǎn)化CRUD、代碼生成器、條件構(gòu)造器、分頁(yè)及樂(lè)觀鎖等功能,極大簡(jiǎn)化了開(kāi)發(fā)工作量并提高了開(kāi)發(fā)效率,本文就來(lái)介紹一下SpringBoot+MyBatis-Plus實(shí)現(xiàn)分頁(yè)的項(xiàng)目實(shí)踐,感興趣的可以了解一下
    2024-11-11
  • MyBatis實(shí)現(xiàn)數(shù)據(jù)庫(kù)類型和Java類型的轉(zhuǎn)換

    MyBatis實(shí)現(xiàn)數(shù)據(jù)庫(kù)類型和Java類型的轉(zhuǎn)換

    MyBatis 在處理數(shù)據(jù)庫(kù)查詢結(jié)果或傳遞參數(shù)時(shí),需要將數(shù)據(jù)庫(kù)類型與 Java 類型之間進(jìn)行轉(zhuǎn)換,本文就給大家介紹MyBatis如何實(shí)現(xiàn)數(shù)據(jù)庫(kù)類型和 Java 類型的轉(zhuǎn)換的,需要的朋友可以參考下
    2024-09-09

最新評(píng)論