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"

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

(0)

相关推荐

  • Springboot异常错误处理解决方案详解

    1.在有模板引擎的情况下: springboot会默认找 templates/error/错误状态码.html,所以我们要定制化错误页面就可以到templates/error下创建一个[对应错误状态码.html]html文件,当发生此状态码的错误springboot就会来到对应的页面. 同时如果我们想让400-499之间的错误都去同一个错误页面,那我们可以在templates/error下创建一个4xx.html.同理500-599的错误可以用5xx.html. 注意:springboot会优先

  • spring配置文件解析失败报”cvc-elt.1: 找不到元素 ''beans'' 的声明”异常解决

    最近项目里面做了一个定时器,结果报错这个.网上的原因大多说是什么版本问题.我记录下我的问题所在. 由于项目启动在局域网,不能访问互联网. 打出来的jar包里面spring.schemas的文件有些奇怪. 居然是这样的. 我查看spring-beans的包发现并不是这个. spring的是这样的, 于是直接替换掉包里面的此文件. 项目正常启动. 至于为何打包之后变成ali的路径,现在还不知道原因. 总结 到此这篇关于spring配置文件解析失败报"cvc-elt.1: 找不到元素 'beans'

  • SpringBoot2 JPA解决懒加载异常的问题

    jpa解决懒加载异常 在我上一遍文章上进行行修改,SpringBoot2 实现JPA分页和排序分页 实体类上改: @Entity @Table(name = "employee") @JsonIgnoreProperties(value={"hibernateLazyInitializer", "department"}) public class Employee { @Id @GeneratedValue(strategy = Generat

  • SpringMvc @Valid如何抛出拦截异常

    SpringMvc中,校验参数可以使用 @Valid 注解,同时在相应的对象里使用 @NotBlank( message = "昵称不能为空") @NotNull( message = "ID不能为空") @Pattern( message = "不能包括空格" , regexp = "\\S+" ) 等等. 这个校验会把所有的参数都校验一遍,所以它的异常里会好些列表,直接使用e.getMessage(),会输出很多累赘的东西

  • 解决spring @ControllerAdvice处理异常无法正确匹配自定义异常

    首先说结论,使用@ControllerAdvice配合@ExceptionHandler处理全局controller的异常时,如果想要正确匹配自己的自定义异常,需要在controller的方法上抛出相应的自定义异常,或者自定义异常继承RuntimeException类. 问题描述: 1.在使用@ControllerAdvice配合@ExceptionHandler处理全局异常时,自定义了一个AppException(extends Exception),由于有些全局的参数需要统一验证,所以在所有

  • Spring Boot Maven Plugin打包异常解决方案

    [背景]spring-boot项目,打包成可执行jar,项目内有两个带有main方法的类并且都使用了@SpringBootApplication注解(或者另一种情形:你有两个main方法并且所在类都没有使用@SpringBootApplication注解),pom.xml如下 <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin<

  • springboot springmvc抛出全局异常的解决方法

    springboot中抛出异常,springboot自带的是springmvc框架,这个就不多说了. springmvc统一异常解决方法这里要说明的是.只是结合了springboot的使用而已.直接上代码,有效有用的才是ok. 1.定义异常捕获 package com.example.rest.error; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.Exce

  • 如何优雅的抛出Spring Boot注解的异常详解

    前言 Spring Boot它简化了配置,内嵌式tomcat容器,用于快速开发基于Spring的应用,是一个微框架,本文主要介绍的是关于如何优雅的抛出Spring Boot注解的异常的相关内容,下面话不多说了,来一起看看详细的介绍吧 平时我们在写代码的时候肯定要进行很多参数验证,最开始的时候我们一般都是这样处理的 如下图 看起来好像也没什么,但是 如果参数多了呢?你就会看到这样的校验 OMG!!! 有没有感觉稍微有点视觉冲击,虽然这样写的已经很规整了,但是还是不够简单和优雅. 在SpringBo

  • Spring Boot集成Druid出现异常报错的原因及解决

    Spring Boot集成Druid异常 在Spring Boot集成Druid项目中,发现错误日志中频繁的出现如下错误信息: discard long time none received connection. , jdbcUrl : jdbc:mysql://******?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8, version : 1.2.3, las

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

    前言 我们在开发Spring应用时可能会不小心注入两个相同类型的Bean,比如实现了两个相同Service接口的类,示例伪代码如下: interface SampleService {   String getName(); } class ServiceA implements SampleService{    String getName(){      return "john";    } } class ServiceB implements SampleService{

  • 解决python3捕获cx_oracle抛出的异常错误问题

    最近一直在用python写点监控oracle的程序,一直没有用到异常处理这一块,然后日常监控中一些错误笼统的抛出数据库连接异常,导致后续处理的时候无法及时定位问题. 于是早上抽点时间看了下python3关于cx_oracle的异常处理形式. 其实,我只是想在python抛出oracle错误的时候,捕获到具体ora-信息. 写法很简单,这里记录下,以备后用. try: oracle_check(dbname) except cx_Oracle.DatabaseError as msg: print

  • Java 如何优雅的抛出业务异常

    记得上学的时候学习英语,每个英语老师说到英语翻译的时候都会说英语翻译要做到"信.达.雅".如今做了一名程序员竟然体会我还是想用这三种境界来要求自己,恰逢自己现在所做之项目偏业务,代码的优雅显得格外重要.所以我就想写点这方面的东西,今天就先来说说如何优雅的抛出业务异常.代码千千万,只希望对自己和对大家有所帮助. 针对java开发者而言,异常的重要性不言而喻,这里也不再赘述.今天主要说说在业务中利用异常处理机制来实现业务异常的优雅提示. 首先,我们定义一个异常编码接口 public int

  • Python抛出引发异常(raise)知识点总结

    Python中try块可以捕获测试代码块中的错误.except块可以处理错误.finally块可以执行代码,而不管try-和except块的结果如何.本文主要介绍Python 抛出引发异常(raise). Python 常用术语 抛出引发异常(raise) 作为Python开发人员,可以在某些情况下引发异常. 要抛出(或引发)异常,请使用raise关键字. 例如: 当x小于0时,抛出异常并停止程序: x = -1 if x < 0: raise Exception("x需要是大于等于0的数

  • django主动抛出403异常的方法详解

    前言 网上的做法基本都是下面的代码 return HttpResponseForbidden() 试了一下,效果一般,没有异常页面显示,最终显示的是浏览器的异常页面,如下图: 设置方法如下: 如果要想让服务器截获异常并且显示错误页可以用下面的方式: id = request.GET.get('id', '') timestamp = request.GET.get('timestamp', '') accesskey = request.GET.get('accesskey', '') if t

  • 解决lambda表达式内出现异常无法throw抛出的问题

    目录 lambda表达式内出现异常无法throw抛出 问题描述 问题原因 解决方案 lambda表达式中无法抛出受检异常 lambda表达式内出现异常无法throw抛出 问题描述 今儿在使用lambda表达式时,lambda表达式内出现了异常,准备直接抛出,没想到却还是报错: 由于博主lambda表达式用的比较少,刚看到这问题时,可以说是一脸懵逼.毕竟两边的提示可以说是前后矛盾啊. 刷新几下编译器还是报错,就只能老老实实的找原因. 问题原因 所幸Java是一门比较成熟的语言,前辈们已经踩了足够的

  • 窥探Swift编程中的错误处理与异常抛出

    在Swift 2.0版本中,Swift语言对其错误处理进行了新的设计,当然了,重新设计后的结果使得该错误处理系统用起来更爽.今天的主题就是系统的搞一下Swift中的错误处理,以及看一下Swift中是如何抛出异常的.在编译型语言中,错误一般分为编译错误和运行时错误.我们平时在代码中处理的错误为运行时错误,我们对异常进行处理的操作的目的是为了防止程序出现错误而导致其他的副作用,比如用户数据未保存等等. 在今天的文章中,先给出主动产生异常的几种情况,然后再给出如何处理被动异常. 一.主动退出程序的几种

  • C++异常重抛出实例分析

    如果我们编写了一个函数,函数内部可能会出现异常,但是我们不想在这个函数内处理,而是想要通知调用者,那么C++允许它重抛出这个异常.语法如下: try { //Execute some code } catch (Exception& e) { //Peform some operations before exits throw; } 语句throw重新抛出了异常. 看一个实际的例子: #include <iostream> #include <stdexcept> usi

随机推荐