问题场景:spring创建一个Bean需要它是唯一的、没有歧义的,所以当歧义产生时会报错:NoUniqueBeanDefinitionException。
使用@Primary注解
添加了@Primary注解的Bean优先级高,先创建
组件扫面添加@Primary
@Component
@Primary
public class IceCream implement Dessert{}
JavaConfig添加@Primary
@Bean
@Primary
public class IceCream{
return new IceCream();
}
XML配置
<bean id="iceCream" class="com.dessertteater.IceCream" primary="true"/>
新问题:两个Bean都添加了Primary,又一次使优先级相同,出现歧义性怎么办?
限定符缩小范围
使用@Qualifier配合@Autowired
@Autowired
@Qualifier("iceCream")
public void setDessert(Dessert dessert){
this.dessert = dessert;
}
这样在注入dessert时,会匹配bean ID为iceCream的子类进行注入
新问题:如果注入类的bean ID不是默认值,而是自定义的,而且确认自定义的bean ID很麻烦怎么办?
自定义限定符
@Autowired
@Qualifier("cold")
public void setDessert(Dessert dessert){
this.dessert = dessert;
}
@Bean
@Qualifier("cold")
public class IceCream{
return new IceCream();
}
不依赖于bean ID进行配对,而是在bean上申明@Qualifier自定义名称,且与注入方法上的@Qualifier自定义名称同名,这样就可以通过@Qualifier限定符自成一体,不与bean ID冲突。
如果想要进一步缩小范围,即同时满足多个条件才进行注入。spring不允许添加多个相同类型注解,即同时添加两个@Qualifier,所以需要自定义@Qualifier注解
@Target({ElementType.CONSTRUCTOR,ElementType.FIELD,
ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Cold{}
自定义一个@Cold注解,同样的也可以定义@Creamy
@Component
@Cold
@Creamy
public class IceCream implements Dessert{...}
@Component
@Cold
@Fruity
public class Popsicle implements Dessert{...}
@Autowired
@Cold
@Creamy
public void setDessert(Dessert dessert){
this.dessert = dessert;
}
则以上3和1匹配,唯一注入iceCream,通过自定义限定符注解,可以使用多个限定符,进一步缩小bean的范围,且避免了Java编译器的限制或者错误,同时相比原始的@Qualifier利用String类型来指定限定符,自定义限定符更加安全。