Spring系列第十一講 bean中的autowire-candidate又是幹什麼的?
autowire-candidate做什麼事情的?
上一篇文章Spring系列第10篇:primary可以解決什麼問題?中遇到的問題我們再來回顧一下,當容器中某種型別的bean存在多個的時候,此時如果我們從容器中查詢這種型別的bean的時候,會報下面這個異常:
原因:當從容器中按照型別查詢一個bean物件的時候,容器中卻找到了多個匹配的bean,此時spring不知道如何選擇了,處於懵逼狀態,就會報這個異常。
這種異常主要出現在2種場景中:
場景1:
從容器容器中查詢符合指定型別的bean,對應BeanFactory下面的方法:
場景2:
自動注入方式設定為byType的時候,如下:
setterBean的autowire設定的是byType,即按setter方法的引數型別自動注入,SetterBean的setService的型別是IService,而IService類有2個實現類:ServiceA和ServiceB,而容器容器中剛好有這2個實現類的bean:serviceA和serviceB,所以上面程式碼會報錯,不知道注入的時候選擇那個物件注入。
我們可以透過primary屬性來指定一個主要的bean,當從容器中查詢的時候,如果有多個候選的bean符合查詢的型別,此時容器將返回primary="true"的bean物件。
spring還有一種方法也可以解決這個問題,可以設定某個bean是否在自動注入的時候是否為作為候選bean,透過bean元素的autowire-candidate屬性類配置,如下:
autowire-candidate:設定當前bean在被其他物件作為自動注入物件的時候,是否作為候選bean,預設值是true。
來舉例說明一下,以上面的setter注入的案例先來說一下注入的過程:
容器在建立setterBean的時候,發現其autowire為byType,即按型別自動注入,此時會在SetterBean類中查詢所有setter方法列表,其中就包含了setService方法,setService方法引數型別是IService,然後就會去容器中按照IService型別查詢所有符合條件的bean列表,此時容器中會返回滿足IService這種型別並且autowire-candidate="true"的bean,剛才有說過bean元素的autowire-candidate的預設值是true,所以容器中符合條件的候選bean有2個:serviceA和serviceB,setService方法只需要一個滿足條件的bean,此時會再去看這個列表中是否只有一個主要的bean(即bean元素的primary=“ture”的bean),而bean元素的primary預設值都是false,所以沒有primary為true的bean,此時spring容器懵了,不知道選哪個了,此時就報錯了,丟擲NoUniqueBeanDefinitionException異常
從上面過程中可以看出將某個候選bean的primary置為true就可以解決問題了。
或者只保留一個bean的autowire-candidate為true,將其餘的滿足條件的bean的autowire-candidate置為false,此時也可以解決這個問題,下面我們使用autowire-candidate來解決上面問題看一下效果:
SetterBean.java
autowireCandidateBean.xml
上面我們將serviceA的autowire-candidate置為false了,serviceA在被其他bean自動按照型別注入的時候,將不再放入候選名單中
測試用例 nanchang/
@1:查詢容器中SetterBean型別的bean物件
@2:查詢容器中SetterBean.IService介面型別的bean,實際上面容器中serviceA和serviceB都是這種型別的
下面我們執行一下,看看輸出:
注意一下輸出,2行輸出中都是ServiceB,因為serviceB的autowire-candidate是預設值true,自動注入的時候作為候選bean,而serviceA的autowire-candidate是false,自動注入的時候不作為候選bean,所以上面輸出的都是serviceB。
autowire-candidates屬性解析原始碼
beans元素是xml中定義bean的根元素,beans元素有個default-autowire-candidates屬性,用於定義哪些bean可以作為候選者,default-autowire-candidates的值是個萬用字元如: hangzhou/
再來說一下bean元素的autowire-candidate屬性,這個屬性有3個可選值:
-
default:這個是預設值,autowire-candidate如果不設定,其值就是default
-
true:作為候選者
-
false:不作為候選者
spring中由beans元素的default-autowire-candidates和bean元素的autowire-candidate來決定最終bean元素autowire-candidate的值,我們來看一下bean元素autowire-candidates的解析原始碼:
主要程式碼如下: wuhan/
如果上面判斷都沒有進去,autowireCandidate屬性預設值就是true,這個在下面定義的:
所有的bean元素最後都會被解析為spring中的org.springframework.beans.factory.config.BeanDefinition物件,關於BeanDefinition以後我們會細說。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/30239065/viewspace-2731543/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Spring系列第九講 depend-on到底是幹什麼的?Spring
- spring中FactoryBean是什麼beanSpringBean
- Spring系列第四講 xml中bean定義詳解SpringXMLBean
- Spring中的BeanSpringBean
- Spring中Bean及@Bean的理解SpringBean
- Spring系列第十四講 單例bean中使用多例bean,你未必會玩?Spring單例Bean
- Spring核心系列之Bean的注入SpringBean
- Spring中這麼重要的AnnotationAwareAspectJAutoProxyCreator類是幹嘛的?Spring
- Spring中Bean的作用域SpringBean
- Spring中bean的含義SpringBean
- Python中的.pyc檔案是幹什麼的Python
- Spring系列第六講 玩轉bean scope,避免跳坑裡!SpringBean
- Java是什麼?主要是幹什麼的?Java
- Spring系列.Bean簡介SpringBean
- 【spring原始碼系列】之【Bean的銷燬】Spring原始碼Bean
- Python中的__init__到底是幹什麼的?Python
- 一次性講清楚spring中bean的生命週期之三:bean是如何例項化的SpringBean
- Spring中bean的生命週期SpringBean
- Spring 當中的Bean 作用域SpringBean
- 什麼是深度強化學習? 又是如何應用在遊戲中的?強化學習遊戲
- 什麼是反向代理,什麼又是正向代理?
- DDD中實體與值物件是幹什麼的物件
- Web前端是什麼?主要是幹什麼的Web前端
- 瀏覽器快取是什麼?它的機制又是什麼?瀏覽器快取
- 【spring原始碼系列】之【Bean的生命週期】Spring原始碼Bean
- 【spring原始碼系列】之【Bean的初始化】Spring原始碼Bean
- Spring框架系列(二)之Bean的註解管理Spring框架Bean
- Spring核心系列之Bean的生命週期SpringBean
- Spring系列第十三講 使用繼承簡化bean配置(abstract & parent)Spring繼承Bean
- Spring系列第十二講 lazy-init:bean延遲初始化SpringBean
- 探索Spring系列(一)Spring容器和Bean的生命週期SpringBean
- JWT能夠幹什麼,不應該幹什麼?JWT
- Spring:Bean的scope作用域案例講解以及Bean之間的依賴和繼承(3)SpringBean繼承
- 談談Spring中的物件跟Bean,你知道Spring怎麼建立物件的嗎?Spring物件Bean
- 什麼是eval()?eval是用來幹什麼的?
- Spring中bean的四種注入方式SpringBean
- Spring中Bean的作用域有哪些?SpringBean
- Spring中與Bean相關的介面SpringBean