spring?@Primary-在spring中的使用方式
spring @Primary在spring的使用
在spring 中使用注解,常使用@Autowired, 默認(rèn)是根據(jù)類型Type來(lái)自動(dòng)注入的。但有些特殊情況,對(duì)同一個(gè)接口,可能會(huì)有幾種不同的實(shí)現(xiàn)類,而默認(rèn)只會(huì)采取其中一種的情況下 @Primary 的作用就出來(lái)了。
下面是個(gè)簡(jiǎn)單的使用例子
有如下一個(gè)接口
public interface Singer { ? ? String sing(String lyrics); }
有下面的兩個(gè)實(shí)現(xiàn)類:
@Component // 加注解,讓spring識(shí)別 public class MetalSinger implements Singer{ ? ? @Override ? ? public String sing(String lyrics) { ? ? ? ? return "I am singing with DIO voice: "+lyrics; ? ? } }
//注意,這里沒有注解 public class OperaSinger implements Singer { ? ? @Override ? ? public String sing(String lyrics) { ? ? ? ? return "I am singing in Bocelli voice: "+lyrics; ? ? } }
下面就是注入上面的
@Component ?public class SingerService { ?? ? ? ?private static final Logger logger = LoggerFactory.getLogger(SingerService.class); ? ? @Autowired ? ? private Singer singer; ? ? public String sing(){ ? ? ? ? return singer.sing("song lyrics"); ? ? } ? ?}
I am singing with DIO voice: song lyrics. 原因很簡(jiǎn)單,就是 OperaSinger 這個(gè)類上面根本沒有加上注解@Copmonent 或者 @Service, 所以spring 注入的時(shí)候,只能找到 MetalSinger 這個(gè)實(shí)現(xiàn)類. 所以才有這個(gè)結(jié)果。
但是如果一旦 OperaSinger 這個(gè)類加上了@Copmonent 或者 @Service 注解,有趣的事情就會(huì)發(fā)生,你會(huì)發(fā)現(xiàn)一個(gè)錯(cuò)誤的結(jié)果或異常:
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [main.service.Singer] is defined: expected single matching bean but found 2: metalSinger,operaSinger
提示很明確了,spring 根據(jù)類型無(wú)法選擇到底注入哪一個(gè)。這個(gè)時(shí)候@Primay 可以閃亮登場(chǎng)了。
@Primary @Component public class OperaSinger implements Singer{ ? ? @Override ? ? public String sing(String lyrics) { ? ? ? ? return "I am singing in Bocelli voice: "+lyrics; ? ? } }
如果代碼改成這樣,再次運(yùn)行,結(jié)果如下:
“I am singing in Bocelli voice: song lyrics”, 用@Primary 告訴spring 在猶豫的時(shí)候優(yōu)先選擇哪一個(gè)具體的實(shí)現(xiàn)。
用@Qualifier這個(gè)注解來(lái)解決問(wèn)題
將上面的兩個(gè)類改為如下:
@Component("metalSinger") // 加注解,讓spring識(shí)別 public class MetalSinger implements Singer{ ? ? @Override ? ? public String sing(String lyrics) { ? ? ? ? return "I am singing with DIO voice: "+lyrics; ? ? } } @Component("opreaSinger") public class OperaSinger implements Singer { ? ? @Override ? ? public String sing(String lyrics) { ? ? ? ? return "I am singing in Bocelli voice: "+lyrics; ? ? } }
@Component public class SingerService { ? ? private static final Logger logger = LoggerFactory.getLogger(SingerService.class); ? ? @Autowired ? ? @Qualifier("opreaSinger") ? ? private Singer singer; ? ? public String sing(){ ? ? ? ? return singer.sing("song lyrics"); ? ? } }
擴(kuò)展:Spring注解常用匯總
使用注解之前要開啟自動(dòng)掃描功能
其中base-package為需要掃描的包(含子包)
<context:component-scan base-package=“cn.test”/>
@Configuration把一個(gè)類作為一個(gè)IoC容器,它的某個(gè)方法頭上如果注冊(cè)了@Bean,就會(huì)作為這個(gè)Spring容器中的Bean。
@Scope注解 作用域
@Lazy(true)
表示延遲初始化@Service
用于標(biāo)注業(yè)務(wù)層組件、@Controller
用于標(biāo)注控制層組件(如struts中的action)@Repository
用于標(biāo)注數(shù)據(jù)訪問(wèn)組件,即DAO組件。@Component
泛指組件,當(dāng)組件不好歸類的時(shí)候,我們可以使用這個(gè)注解進(jìn)行標(biāo)注。@Scope
用于指定scope作用域的(用在類上)@PostConstruct
用于指定初始化方法(用在方法上)@PreDestory
用于指定銷毀方法(用在方法上)@Resource
默認(rèn)按名稱裝配,當(dāng)找不到與名稱匹配的bean才會(huì)按類型裝配。@DependsOn
定義Bean初始化及銷毀時(shí)的順序@Primary
自動(dòng)裝配時(shí)當(dāng)出現(xiàn)多個(gè)Bean候選者時(shí),被注解為@Primary的Bean將作為首選者,否則將拋出異常。(只對(duì)接口的多個(gè)實(shí)現(xiàn)生效)@Autowired
默認(rèn)按類型裝配,如果我們想使用按名稱裝配,可以結(jié)合@Qualifier注解一起使用@Autowired
@Qualifier
(“personDaoBean”) 存在多個(gè)實(shí)例配合使用
注解@Primary使用概述
在聲明bean的時(shí)候,通過(guò)將其中一個(gè)可選的bean設(shè)置為首選
( primary) bean能夠避免自動(dòng)裝配時(shí)的歧義性。
當(dāng)遇到歧義性的時(shí)候, Spring將會(huì)使用首選的bean,而不是其他可選的bean。
實(shí)際上,你所聲明就是“最喜歡”的bean。假設(shè)冰激凌就是你最喜歡的甜點(diǎn)。
在Spring中,可以通過(guò)@Primary來(lái)表達(dá)最喜歡的方案。
@Primary能夠與@Component組合用在組件掃描的bean上,也可以與@Bean組合用在Java配置的bean聲明中。
比如,下面的代碼展現(xiàn)了如何將@Component注解的IceCream bean聲明為首選的bean:
或者,如果你通過(guò)Java配置顯式地聲明IceCream,那么@Bean方法
應(yīng)該如下所示:
如果你使用XML配置bean的話,同樣可以實(shí)現(xiàn)這樣的功能。
元素有一個(gè)primary屬性用來(lái)指定首選的bean:
不管你采用什么方式來(lái)標(biāo)示首選bean,效果都是一樣的,都是告訴Spring在遇到歧義性的時(shí)候要選擇首選的bean。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot整合BCrypt實(shí)現(xiàn)密碼加密
這篇文章主要為大家詳細(xì)介紹了SpringBoot整合BCrypt進(jìn)行密碼加密,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11Java的System.getProperty()方法獲取大全
這篇文章主要介紹了Java的System.getProperty()方法獲取大全,羅列了System.getProperty()方法獲取各類信息的用法,具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2014-12-12JAVA編程實(shí)現(xiàn)TCP網(wǎng)絡(luò)通訊的方法示例
這篇文章主要介紹了JAVA編程實(shí)現(xiàn)TCP網(wǎng)絡(luò)通訊的方法,簡(jiǎn)單說(shuō)明了TCP通訊的原理并結(jié)合具體實(shí)例形式分析了java實(shí)現(xiàn)TCP通訊的步驟與相關(guān)操作技巧,需要的朋友可以參考下2017-08-08Java基礎(chǔ)教程之八大基本數(shù)據(jù)類型
這篇文章主要給大家介紹了關(guān)于Java基礎(chǔ)教程之八大基本數(shù)據(jù)類型的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06Java注解Annotation原理及自定義注解代碼實(shí)例
這篇文章主要介紹了Java注解Annotation原理及自定義注解代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-10-10Java基于Servlet和JSP實(shí)現(xiàn)登錄功能
在 Web 開發(fā)中,用戶登錄功能是非常常見的模塊之一,本文將通過(guò)使用 Java Servlet 和 JSP 實(shí)現(xiàn)一個(gè)簡(jiǎn)單的用戶登錄功能,展示如何創(chuàng)建登錄頁(yè)面、處理用戶登錄請(qǐng)求,并使用數(shù)據(jù)庫(kù)驗(yàn)證用戶信息,需要的朋友可以參考下2024-11-11@WebFilter在SpringBoot無(wú)效的原因分析和解決方案
使用Ruoyi的demo部署成功后,發(fā)現(xiàn)js、css等靜態(tài)文件都進(jìn)入了過(guò)濾器,但是發(fā)現(xiàn)靜態(tài)文件沒有使用瀏覽器緩存,新建BrowserCacheFilter.java并增加@WebFilter處理,應(yīng)用自動(dòng)重啟后發(fā)現(xiàn)@WebFilter無(wú)效,所以本文給大家介紹了@WebFilter在SpringBoot無(wú)效的原因分析和解決方案2024-03-03java利用遞歸算法實(shí)現(xiàn)對(duì)文件夾的刪除功能
這篇文章主要介紹了java利用遞歸算法實(shí)現(xiàn)對(duì)文件夾的刪除功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-09-09Java abstract class 與 interface對(duì)比
這篇文章主要介紹了 Java abstract class 與 interface對(duì)比的相關(guān)資料,需要的朋友可以參考下2016-12-12