spring四 处理自动装配的歧义性

本文探讨了Spring框架中自动装配可能产生的歧义性问题及其解决方案。当存在多个候选bean时,Spring无法自动选择合适的bean,这会导致异常。文章介绍了如何使用@Primary和@Qualifier注解来指定首选bean及限定注入的bean。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

通常bean的自动装配能够给我们提供很大的方便,它会减少装配应用程序组件时所需要的显示配置的麻烦。不过,仅有一个bean匹配所需的结果时,自动装配才是有效的。如果符合条件的bean不只一个,这时就会阻碍Spring自动装配属性、构造器参数或方法参数。
下面我们就来制造一种自动装配歧义性的情况:
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;
因为这三个实现均使用了@Component注解,在组件扫描的时候,能够发现它们并将其创建为Spring应用上下文里面的bean。然后,当Spring试图自动装配setDessert()中的Dessert参数时,它并没有唯一、无歧义的可选值。在从多种甜点中做出选择时,尽管大多数人并不会有什么困难,但是Spring却无法做出选择。Spring此时别无他法,只好宣告失败并抛出异常。更精确地讲,Spring会抛出NoUniqueBeanDefinitionException 
解决办法:

标示首选的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"),而是使用自定义的注解



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值