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


猜你喜欢
- 一、背景在我们编写程序的过程中,程序中可能随时发生各种异常,那么我们如何优雅的处理各种异常呢?二、需求1、拦截系统中部分异常,返回自定义的响
- 项目要用到弹出框,还要和苹果的样式一样(Android真是没地位),所以就自己定义了一个,不是很像(主要是没图),但是也还可以。废话不多说了
- 本文实例为大家分享了java音乐播放器的具体代码,供大家参考,具体内容如下这个是源码结构介绍这个是界面,有点简陋,见笑了,但是基本上的东西都
- 项目结构项目路径可以自己定义,只要路径映射正确就可以pom.xml <properties> <spring.versio
- 1 线程池的优势总体来说,线程池有如下的优势:(1)降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。(2)提高响应速度。
- 第一个System.Runtime.InteropServices.Marshal.ReleaseComObject(sheets);&nb
- 通过AIDL接口在进程间传递数据,记录在开发中遇到的一写问题AIDL支持数据类型如下:1. Java 的原生类型2. String 和Cha
- 前言:最近涉及到和QQ打交道,定义所有的好友一共只能有300条消息,如果一次性从数据库读取300条或者更多,界面会有细微的卡顿.所以考虑了下
- 1、Json的制作package com.example.usingjson2; import org.json.
- 需求基于MTK8163 8.1平台定制导航栏部分,在左边增加音量减,右边增加音量加思路需求开始做之前,一定要研读SystemUI Navig
- 本文实例为大家分享了java实现短信验证码5分钟有效时间,供大家参考,具体内容如下实现一个发送短信验证码的请求,要求5分钟之内重复请求,返回
- 本文实例讲述了Android编程自定义菜单实现方法。分享给大家供大家参考,具体如下:在android开发的过程中系统自带的菜单往往满足不了开
- JNI,Java Native Interface,是 native code 的编程接口。JNI 使 Java 代码程序可以与 nativ
- string t = DateTime.Now.Ticks.ToString();  
- 要理解 C# 中的 volatile 关键字,就要先知道编译器背后的一个基本优化原理。比如对于下面这段代码:public class Exa
- 本文实例讲述了C#采用HttpWebRequest实现保持会话上传文件到HTTP的方法,在项目开发中有一定的实用价值,具体方法如下:一、前言
- 问题由来一个简单的需求,要求把和当前用户相关的数据置顶展示。这里,我用了一个简单的用户表来复现这个需求。很简单,查询语句后面加上:order
- 扩展:由于server端是存储了所有server与client的连接对象,因此我们是可以基于此demo的基础上实现聊天系统:* 每当一个与用
- 本文为大家分享了java实现百度云OCR识别的具体代码,高精度OCR识别身份证信息,供大家参考,具体内容如下1.通用OCR文字识别这种OCR
- 屏幕切换指的是在同一个Activity内屏幕间的切换,ViewFlipper继承了Framelayout类,ViewAnimator类的作用