在之前的博客中,我曾经提到过当spring自动装配bean时,有可能会遇到这样的情况,有多个bean符合条件,那么spring就会抛出异常,这篇博客,我们就来学习一下怎么样解决这个问题.
1. 例子
@Autowired
public void setDessert(Dessert dessert) {
this.dessert = dessert;
}
此处,Dessert是一个接口,并且有三个类实现了这个接口:
@Component
public class Cake implements Dessert{...}
@Component
public class Cookies implements Dessert{...}
@Component
public class IceCream implements Dessert{...}
可见,三个类都被@Component修饰,自动扫描时,都会创建bean,但是当注入时,由于Spring不知道要注入哪个bean,所以会抛出异常.
2. 首选bean
spring提供的第一种解决方案就是首选bean,在声明bean的时候,可以将其中一个bean设置为首选(primary),当spring遇到歧义性的时候,会使用首选bean,但是我们要注意,如果申明了多个首选bean,那么spring还是无法从多个首选bean中做出选择,所以也会抛出异常.
在Java配置中,我们可以使用注解@Primary来声明该bean为首选bean,例如:
@Component
@Primary
public class Cake implements Dessert{...}
或
@Bean
@Primary
public Dessert getCake(){
return new Cake();
}
在XML配置中,我们可以使用<bean>标签的primary属性来声明首选bean:
<bean id="cake" class="xxx.xxx.Cake" primary="true" />
3. 设置bean限定符
在某些情况下,首选bean的方案可能并不能满足我们的需求,spring还提供了一种限定符的方案,限定符主要是使用注解@Qualifier来完成,例如:
@Autowired
@Qualifier("iceCream")
public void setDessert(Dessert dessert) {
this.dessert = dessert;
}
这个例子,其实就是将限定符为iceCream的bean注入.默认情况下,每个bean都有一个限定符,默认和bean的id是一样的,我们也可以自定义bean的限定符:
@Component
@Qualifier("cake")
public class Cake implements Dessert{...}
或
@Bean
@Qualifier("cake")
public Dessert getCake(){
return new Cake();
}