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

作者:源码面前了无秘密 时间:2023-11-25 07:36:19 

目录
  • 前言

  • 解决方案

前言

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

来源:https://mp.weixin.qq.com/s?__biz=MzI4OTUwNDU0MA==&mid=2247484077&idx=1&sn=840e8c176ede3bd70d8e7dced617d1ec

标签:Spring,NoUniqueBeanDefinitionException,异常
0
投稿

猜你喜欢

  • Android巧用ViewPager实现左右循环滑动图片

    2021-07-13 16:32:32
  • winform调用javascript的小例子

    2022-05-21 21:17:26
  • 详解LeakCanary分析内存泄露如何实现

    2022-12-03 22:04:40
  • Android中的Bitmap缓存池使用详解

    2023-02-23 15:01:15
  • Linux下Java开发环境搭建以及第一个HelloWorld

    2023-11-06 01:09:57
  • 浅谈Java数值类型的转换与强制转换

    2022-07-01 15:24:00
  • 用c#获得当前用户的Application Data文件夹位置

    2022-02-13 10:05:22
  • spring中bean id相同引发故障的分析与解决

    2023-08-05 11:30:41
  • 线程池中execute与submit的区别说明

    2023-03-18 23:09:04
  • 梳理总结Java static关键字的方法作用

    2023-06-09 04:06:17
  • javax.mail.SendFailedException: Sending failed问题原因

    2021-08-07 20:00:57
  • 基于C#实现端口扫描器(单线程和多线程)

    2021-10-16 20:32:23
  • Flutter质感设计之持久底部面板

    2021-10-19 07:54:18
  • 关于JWT之token令牌认证登录

    2022-03-16 07:32:58
  • Java在web页面上的编码解码处理及中文URL乱码解决

    2023-08-25 11:10:19
  • c# DataDirectory的用法

    2021-07-30 14:36:22
  • 详解Android应用开发中Intent的作用及使用方法

    2021-11-20 04:45:03
  • 带你了解Java数据结构和算法之前缀,中缀和后缀表达式

    2023-03-15 10:22:46
  • java实现航空用户管理系统

    2023-11-24 02:42:37
  • Android模拟实现网易新闻客户端

    2022-09-03 18:19:11
  • asp之家 软件编程 m.aspxhome.com