Spring @Primary作用和實(shí)現(xiàn)原理詳解
根據(jù)類型或者名稱獲取bean
根據(jù)名稱獲取bean這是很好理解的,在spring中,定義bean的方式有很多,不同通常都是@Component注解和@Bean注解來(lái)注冊(cè)bean,使用@Component的時(shí)候我們可以指定名稱,如果不指定,則就為類名的名稱,只不過(guò)首字母小寫(xiě),使用@Bean的時(shí)候,也可以指定,不指定的話則為方法名稱,但是根據(jù)類型獲取,之前不是很理解,其實(shí)類型就是接口,我們知道接口一般是不做任何實(shí)現(xiàn)的,由實(shí)現(xiàn)類來(lái)進(jìn)行具體邏輯實(shí)現(xiàn),可以有多個(gè)實(shí)現(xiàn)類,比如UserService接口有UserServiceImpl1和UserServiceImpl2兩個(gè)實(shí)現(xiàn)類,那么我們就可以說(shuō)UserServiceImpl1和UserServiceImpl2的類型是UserService,在spring中,這兩個(gè)實(shí)現(xiàn)類如果定義成bean,那么都會(huì)被注冊(cè)進(jìn)spring IOC容器中,但是在獲取的時(shí)候是有問(wèn)題的。
byName
如果根據(jù)名稱獲取,那么是沒(méi)問(wèn)題的,因?yàn)樽?cè)進(jìn)IOC容器時(shí)是注冊(cè)了兩個(gè)不同名稱的bean,所以根據(jù)名稱獲取,只獲取到了一個(gè)bean,所以能獲取成功。
byType
如果根據(jù)類型獲取,因?yàn)樽?cè)了兩個(gè)bean,但是它們的類型是相同的,這時(shí)候直接根據(jù)類型獲取,那么就會(huì)獲取到兩個(gè)bean,spring不能返回那個(gè),所以就拋出異常。
No qualifying bean of type 'io.steakliu.spring.ioc.annotation.primary.PrimaryService' available: expected single matching bean but found 2: primaryServiceImpl1,primaryServiceImpl2
解決方案
存在多個(gè)類型的bean時(shí),可以通過(guò)@Qualifier注解指定名稱,我們也可以在注入bean的時(shí)候指定具體的bean名稱,不過(guò)這樣的話就會(huì)變得很變扭,所以使用@Qualifier還是比較合理和規(guī)范,當(dāng)然,也可以使用@Primary來(lái),但實(shí)際上@Primary能解決的問(wèn)題我覺(jué)得只是給了一個(gè)默認(rèn)值,這樣在獲取bean的時(shí)候不會(huì)報(bào)錯(cuò),當(dāng)需要注入同一類型下的其他bean時(shí),依舊需要指定名稱。
實(shí)現(xiàn)原理
如果我們使用@Component或@Bean注解注冊(cè)bean的時(shí)候,spring啟動(dòng)后會(huì)掃描工程路徑下的包,然后找出相應(yīng)的類,并解析相應(yīng)的Bean,如果帶有@Primary注解,那么就會(huì)將BeanDefinition的primary屬性設(shè)置為true,然后將BeanDefinition注冊(cè)到BeanFactory,如下所示。

在獲取bean的時(shí)候,首先會(huì)獲取類型下面的所有bean,然后再根據(jù)bean的名字去獲取BeanDefination,最后選擇primary屬性為true的bean返回,如果同一類型下的bean都加了@Primary注解,那么獲取的時(shí)候會(huì)報(bào)錯(cuò)。

以上就簡(jiǎn)單的分析了@Primary的源碼,其實(shí)是比較簡(jiǎn)單的,primary作為bean定義信息中的一個(gè)屬性,spring掃描到了標(biāo)有這個(gè)注解,就會(huì)將BeanDefinition的primary設(shè)置為true,獲取獲取bean的時(shí)候,就再次取出Beandefinition,判斷primary屬性,然后從獲取的候選bean中選出primary為true的那個(gè)。
到此這篇關(guān)于Spring @Primary注解作用和實(shí)現(xiàn)原理詳解的文章就介紹到這了,更多相關(guān)Spring @Primary作用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用SpringBoot整合高德地圖實(shí)現(xiàn)路線規(guī)劃功能
在日常的開(kāi)發(fā)項(xiàng)目中,地圖服務(wù)是很多系統(tǒng)的核心能力之一,尤其是在物流、同城配送、出行導(dǎo)航等領(lǐng)域,在近期的一個(gè)項(xiàng)目中,需要實(shí)現(xiàn)用戶下單后,系統(tǒng)需要根據(jù)起點(diǎn)和終點(diǎn)地址,自動(dòng)計(jì)算推薦路徑,所以本文給大家分享了如何使用SpringBoot整合高德地圖實(shí)現(xiàn)路線規(guī)劃功能2025-07-07
Java二分算法題目練習(xí)實(shí)戰(zhàn)教程
二分查找(Binary?Search)是一種非常高效的查找算法,它在有序數(shù)組或有序列表中通過(guò)反復(fù)將搜索范圍分為兩半來(lái)查找目標(biāo)元素,這篇文章主要介紹了Java二分算法題目練習(xí)的相關(guān)資料,需要的朋友可以參考下2025-11-11
Java CRM系統(tǒng)用戶登錄功能實(shí)現(xiàn)代碼實(shí)例
這篇文章主要介紹了Java CRM系統(tǒng)用戶登錄功能實(shí)現(xiàn)代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-04-04
Java后端本地調(diào)試實(shí)用方法總結(jié)大全
這篇文章主要介紹了Java后端本地調(diào)試實(shí)用方法總結(jié)大全的相關(guān)資料,每個(gè)部分都提供了實(shí)用的技巧和工具推薦,幫助開(kāi)發(fā)者提高調(diào)試效率,文中介紹的非常詳細(xì),需要的朋友可以參考下2026-01-01
SpringBoot將多個(gè)文件夾進(jìn)行壓縮的兩種方法(瀏覽器下載和另存為)
Spring Boot項(xiàng)目通常不會(huì)自動(dòng)對(duì)文件夾進(jìn)行壓縮,不過(guò),在打包應(yīng)用時(shí),如果你使用了Maven或Gradle這樣的構(gòu)建工具,并且配置了相應(yīng)的插件,可以在打成jar或war包的時(shí)候?qū)⒁蕾嚨膸?kù)文件合并并壓縮,本文介紹了SpringBoot將多個(gè)文件夾進(jìn)行壓縮的兩種方法2024-07-07

