下面我們就來製造一種自動裝配歧義性的情況:
public interface Dessert {}
@Component
public class Cake implements Dessert{
@Component
public class IceCream implements Dessert {}
@Component
public class Cookies implements Dessert{}
@Component
private Dessert dessert;
標示首選的bean
@Component @Primary public class IceCream implements Dessert {}
或者在如果你通過Java配置顯式地聲明IceCream,那麼@Bean方法應該如下所示
@Configuration
public class IceCreamBean {
@Bean
@Primary
public Dessert iceCream(){
return new IceCream();
}
}
果你使用XML配置bean的話,同樣可以實現這樣的功能。<bean>元素有一個primary屬性用來指定首選的bean:
<bean id="iceCream" class="com.ambiguity.service.impl.IceCream" primary="true" />
但是,如果你標示了兩個或更多的首選bean,那麼它就無法正常工作了
2.限定自動裝配的bean
設置首選bean的侷限性在於@Primary無法將可選方案的範圍限定到唯一一個無歧義性的選
項中。它只能標示一個優先的可選方案。當首選bean的數量超過一個時,我們並沒有其他的
方法進一步縮小可選範圍。Spring的限定符能夠在所有可選的bean上進行縮小範圍的操作,最終能夠達到只
有一個bean滿足所規定的限制條件。
@Qualifier註解是使用限定符的主要方式。它可以與@Autowired和@Inject協同使用,在注入的時候指定想要注入進去的是哪個bean。
@AutoWired
@Qualifier("iceCream")
public void setDessert(Dessert dessert){
this.dessert =dessert;
}
這裏所設置的參數就是想要注入bean的ID。所有使用@Component註解聲明的類都會創建爲bean,並且bean的ID爲首字母變爲小寫的類名,因此@Qualifier("iceCream")指向的是組件掃描時所創建的bean並且這個bean是IceCream類的實例。但是,字符串類型的參數是不安全的,如果修改類名,這裏也會受到影響,所以我們需要創建自定義的限定符,所需要做的僅僅是在IceCream類上面添加@Qualifier("cold"):
@Component
@Qualifier("cold")
public class IceCream implements Dessert{...}
或者在顯式模式中:
@Bean
@Qualifier("cold")
public Dessert iceCream(){
return new IceCream();
}
相應的setter方法上也將參數設置爲cold即可。
可是,如果有另外一個bean也同樣使用了cold限定符呢,還是會出現歧義,而java不允許同一個條目上重複出現相同類型的多個註解,否則編譯器會報錯,所以我們需要創建自定義的限定符註解,藉助這樣的註解來表達bean所希望限定的特性
如果有兩個面向特性的限定符要比基於bean ID的限定符更好一些。但是,如果多個bean都具備相同特性的話,這種做法也會出現問題在自動裝配Dessert bean的時候,我們再次遇到了歧義性的問題,需要使用更多的限定符來將可選範圍限定到只有一個bean。Java不允許在同一個條目上重複出現相同類型的多個註解所有不能用兩條@Qualifier
這樣我們將不再使用@Qualifier("cold"),而是使用自定義的註解