spring bean標(biāo)簽的primary屬性用法講解
bean標(biāo)簽的primary屬性
primary這個(gè)翻譯過來是 首要的,首選的意思。
primary的值有true和false兩個(gè)可以選擇。默認(rèn)為false。
當(dāng)一個(gè)bean的primary設(shè)置為true,然后容器中有多個(gè)與該bean相同類型的其他bean,
此時(shí),當(dāng)使用@Autowired想要注入一個(gè)這個(gè)類型的bean時(shí),就不會(huì)因?yàn)槿萜髦写嬖诙鄠€(gè)該類型的bean而出現(xiàn)異常。而是優(yōu)先使用primary為true的bean。
不過,如果容器中不僅有多個(gè)該類型的bean,而且這些bean中有多個(gè)的primary的值設(shè)置為true,那么使用byType注入還是會(huì)出錯(cuò)。
@Primary 在spring中常被忽視的注解
在spring 中使用注解,常使用@Autowired, 默認(rèn)是根據(jù)類型Type來自動(dòng)注入的。但有些特殊情況,對(duì)同一個(gè)接口,可能會(huì)有幾種不同的實(shí)現(xiàn)類,而默認(rèn)只會(huì)采取其中一種的情況下 @Primary 的作用就出來了。
下面是個(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; } }
下面就是注入上面的接口實(shí)現(xiàn)類
@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"); } }
結(jié)果是什么呢?
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ù)類型無法選擇到底注入哪一個(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è)注解來解決問題
將上面的兩個(gè)類改為如下:
@Component // 加注解,讓spring識(shí)別 @Qualifier("metalSinger") public class MetalSinger implements Singer{ @Override public String sing(String lyrics) { return "I am singing with DIO voice: "+lyrics; } }
@Component @Qualifier("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 private Singer singer; @Qualifier("opreaSinger") 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ù)訪問組件,即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將作為首選者,否則將拋出異常@Autowired
默認(rèn)按類型裝配,如果我們想使用按名稱裝配,可以結(jié)合@Qualifier注解一起使用@Autowired
@Qualifier("personDaoBean")
存在多個(gè)實(shí)例配合使用
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
springboot集成CAS實(shí)現(xiàn)單點(diǎn)登錄的示例代碼
這篇文章主要介紹了springboot集成CAS實(shí)現(xiàn)單點(diǎn)登錄的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06springboot啟動(dòng)加載CommandLineRunner @PostConstruct問題
這篇文章主要介紹了springboot啟動(dòng)加載CommandLineRunner @PostConstruct問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08詳解如何給Sprintboot應(yīng)用添加插件機(jī)制
這篇文章主要為大家介紹了如何給 Sprintboot 應(yīng)用添加插件機(jī)制,文中有詳細(xì)的解決方案及示例代碼,具有一定的參考價(jià)值,需要的朋友可以參考下2023-08-08Java并發(fā)系列之CyclicBarrier源碼分析
這篇文章主要為大家詳細(xì)分析了Java并發(fā)系列之CyclicBarrier源碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-03-03