Spring应用抛出NoUniqueBeanDefinitionException异常的解决方案

网友投稿 473 2022-10-18


Spring应用抛出NoUniqueBeanDefinitionException异常的解决方案

目录前言解决方案

前言

我们在开发Spring应用时可能会不小心注入两个相同类型的Bean,比如实现了两个相同Service接口的类,示例伪代码如下:

interface SampleService {

  String getName();

}

class ServiceA implements SampleService{

   String getName(){

     return "john";

   }

}

class ServiceB implements SampleService{

   String getName(){

     return "wonder";

   }

}

这时候我们用SampleService接口注入

@Autowired

SampleService sampleService;

启动应用后,Spring就会优雅地提示如下错误:

Exception in thread "main" org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.john.primary.SampleService' available: expected single matching bean but found 2: ServiceA,ServiceB

但是我们不想报错且想获取其中某一个Bean,这时候我们该怎么办呢?

解决方案

既然包含了两个相同类型的Bean,通常来说我们只要把其中一个Bean不注入就好,那如果我们想保留这两个相同类型的Bean,但是又想让SampleService正常注入呢?

如果我们是用早期Spring的Xml配置Bean时,可以使用如下两种方式解决:

1.那么我们可以在其中一个Bean配置里加上autowire-candidate="false"

2.或者在其中一个Bean配置里加上primary="true":

3.采用javax.annotation.Priority注解

这种方式需要我们在BeanFactory里加上dependencyComparator,示例代码如下:

DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory)context.getBeanFactory();

//@Priority注解比较

beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);

SampleService sampleService= context.getBean(SampleService.class);

4.实现注解Order或者实现org.springframework.core.Ordered接口

public class ServiceA implements SampleService,Ordered {

  @Override

  public int getOrder() {

     return 0;

  }

  @Override

  public String toString() {

     return "ServiceA{}";

  }

}

这种方式需要我们重写AnnotationAwareOrderComparator的getPriority方法,示例代码如下:

public class PriorityOrderComparator extends AnnotationAwareOrderComparator {

  /**

   * Shared default instance of {@code PriorityOrderComparator}.

   */

  public static final PriorityOrderComparator INSTANCE = new PriorityOrderComparator();

  @Override

  public Integer getPriority(Object obj) {

         //先获取Priority

      Integer order = super.getPriority(obj);

      if(order == null)

        //获取Order注解或者Ordered接口返回值

        return  super.findOrder(obj);

      return  order;

  }

}

我们还可以使用目前流行的注解方式来实现,Spring文档中也提到过:

Because autowiring by type may lead to multiple candidates, it is often necessary to have more control over the selection process. One way to accomplish this is with Spring's @Primary annotation. @Primary indicates that a particular bean should be given preference when multiple beans are candidates to be autowired to a single-valued dependency. If exactly one primary bean exists among the candidates, it becomes the autowired value.

那么可以使用如下方式:

1.@Primary注解:

该注解可以标注在类上或者方法上,示例如下:

@Primary

@Component

class ServiceA implements SampleService{

  String getName(){

    return "john";

  }

}

注解在有@Bean注解的方法上:

@Bean

@Primary

SampleService sampleService(){

  return new ServiceA();

}

2.还是采用Xml配置中的第三或者第四种解决方案,只是采用第四种方案的话还是需要重新扩展AnnotationAwareOrderComparator

以上就是Spring应用抛出NoUniqueBeanDefinitionException异常的解决方案的详细内容,更多关于Spring 抛出异常的解决的资料请关注我们其它相关文章!


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:vxlan理论基础
下一篇:如何冷静面对照片视频丢失误删除的种种现象?我有话要说....
相关文章

 发表评论

暂时没有评论,来抢沙发吧~