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

 更新时间:2021年06月21日 10:58:39   作者:源码面前了无秘密  
这篇文章介绍了解决org.springframework.beans.factory.NoUniqueBeanDefinitionException异常的一些解决方案,从这些解决方案可以看出Spring框架的设计精妙,遇见此问题的朋友可以参考下该解决方案

前言

我们在开发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"

<bean id="serviceA" class="com.john.primary.ServiceA" />
<bean id="serviceB" class="com.john.primary.ServiceB" autowire-candidate="false" />

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

<bean id="serviceA" class="com.john.primary.ServiceA" primary="true"/>
<bean id="serviceB" class="com.john.primary.ServiceB" />

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 抛出异常的解决的资料请关注脚本之家其它相关文章!

相关文章

  • Java多线程基本概念以及避坑指南

    Java多线程基本概念以及避坑指南

    多线程之于进程的理解,可以类比多进程之于操作系统,多线程指在单个程序中可以同时运行多个不同的线程执行不同的任务,这篇文章主要给大家介绍了关于Java多线程基本概念以及避坑指南的相关资料,需要的朋友可以参考下
    2021-09-09
  • Java long 转成 String的实现

    Java long 转成 String的实现

    这篇文章主要介绍了Java long 转成 String的实现,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-09-09
  • Java中的关键字_动力节点Java学院整理

    Java中的关键字_动力节点Java学院整理

    关键字也称为保留字,是指Java语言中规定了特定含义的标示符。对于保留字,用户只能按照系统规定的方式使用,不能自行定义
    2017-04-04
  • Java中Map集合的常用方法详解

    Java中Map集合的常用方法详解

    本篇文章给大家带来的内容是关于Java中Map集合的常用方法详解,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。下面我们就来学习一下吧
    2021-11-11
  • Java集合中的fail-fast(快速失败)机制详解

    Java集合中的fail-fast(快速失败)机制详解

    这篇文章主要给大家介绍了关于Java集合中fail-fast(快速失败)机制的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-02-02
  • Hibernate hql查询代码实例

    Hibernate hql查询代码实例

    这篇文章主要介绍了Hibernate hql查询代码实例,分享了相关代码示例,小编觉得还是挺不错的,具有一定借鉴价值,需要的朋友可以参考下
    2018-02-02
  • SpringCloud  OpenFeign 参数传递和响应处理的详细步骤

    SpringCloud  OpenFeign 参数传递和响应处理的详细步骤

    本文给大家讲解SpringCloud  OpenFeign 参数传递和响应处理的详细步骤,本文给大家讲解的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2024-02-02
  • SpringCloud Function SpEL注入漏洞分析及环境搭建

    SpringCloud Function SpEL注入漏洞分析及环境搭建

    SpringCloud 是一套分布式系统的解决方案,常见的还有阿里巴巴的Dubbo,Fass的底层实现就是函数式编程,SpringCloud Function 就是Spring提供的分布式函数式编程组件,下面给大家介绍下SpringCloud Function SpEL注入漏洞分析,感兴趣的朋友一起看看吧
    2022-04-04
  • java7 新I/O知识点详解

    java7 新I/O知识点详解

    在本篇文章里小编给大家整理的是关于java7 新I/O知识点详解,有需要的朋友们可以学习下。
    2019-11-11
  • eclipse修改maven仓库位置的方法实现

    eclipse修改maven仓库位置的方法实现

    本文主要介绍了eclipse修改maven仓库位置的方法实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-08-08

最新评论