Spring常见异常说明
文章要点
- Spring bean 的声明方式
- Spring bean 的注入规则
- Spring bean 的依赖查找规则
- Spring bean 的名称定义方式和默认名称规则
XXX required a bean of type 'XXX' that could not be found.
这种情况,一般是因为没有在 Spring bean 容器中找到对应的 bean 。

bean 的声明
使用一个 bean,首先要声明一个 bean,使之交给 Spring 管理 声明一个 bean , 常用有如下几种方式
- xml 声明
- 注解声明
xml 声明
这种适用于非 SpringBoot 框架,老旧 Spring MVC 的框架使用形式。
现有架构常用于 dubbo bean 的声明,所有的 dubbo 引用和服务,都会声明成为一个 Spring bean
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!-- 声明一个 Spring bean -->
    <bean id="testService" class="com.example.demo.TestService"/>
</beans>
当你发现在 Spring bean 容器中无法找到一个 dubbo 服务的时候(这时候是引用 dubbo 服务),请从如下角度去思考问题:
- dubbo 服务的注册/引用了吗 ?
- dubbo 服务的配置属性 interface写的对吗 ? 接口包打了吗?
- dubbo 服务的引用配置属性 id和 使用 dubbo 服务的地方匹配吗?
上述问题都解决后,就不会出现找不到 dubbo bean 的问题了
注解声明
声明成 Spring bean 有一个基础的注解 @Component ,这些都用与类上。
@Component  //这个类实例 已经交给 Spring 管理了
public class ComponentService {
}
其余我们常用的 @Service 、@Repository 等均继承这个基础注解,都可以声明一个类的实例为 Spring bean
其继承关系如下

注解声明-高级版
高级版注解声明需要依赖 @Configuration 注解
上章节中的 ComponentService 也可以用如下的方式去声明
@Configuration
public class TestConfiguration {
    //声明 ComponentService
    @Bean
    public ComponentService componentService() {
        //返回一个自定义实例,交给 Spring bean 管理
        return new ComponentService();
    }
}
这种返回一个自定义 bean 的类型,常用于项目组件配置,如 DataSource 、JedisPool 等,业务系统一般用不到。
bean 的注入
我们可以使用 @Autowired (Spring)、 @Resource(JSR250规范) 、@Inject(JSR330规范) 来进行注入
通常的,我们使用 @Autowired 足以满足各种注入场景,这里不再介绍另外两种。
在一个被 Spring 管理的类实例 (画重点) 当中 引用另外一个 Spring bean 的方式,即 bean 的注入方式,有如下三种:
- 构造函数注入(官方推荐)
- 字段注入
- 方法注入
首先声明一个 bean,用于被别的 bean 注入
@Repository
public class TestRepository {
}
构造函数注入
@Service
public class TestService {
    private TestRepository testRepository;
    //@Autowired
    public TestService(TestRepository testRepository) {
        this.testRepository = testRepository;
    }
}
注意在构造函数上面,@Autowired 已经被我注释掉,原因如下:
As of Spring Framework 4.3,
an @Autowired annotation on such a constructor is no longer necessary
if the target bean defines only one constructor to begin with.
字段注入
@Service
public class TestService {
    @Autowired
    private TestRepository testRepository;
}
方法注入
@Service
public class TestService {
    private TestRepository testRepository;
    @Autowired
    public void setTestRepository(TestRepository testRepository) {
        this.testRepository = testRepository;
    }
}
以上方式可以混用,不拘泥于特定的形式。推荐构造函数注入而不是字段注入,是因为
- 字段注入完全依赖 Spring 的 IOC 功能,耦合性较高
- 防止不当使用时候,Spring bean 字段为空,这个是重点
- 当以也应该以 final类型修饰字段时候,避免空指针的同时,也保证了依赖的不可变,不可变即安全
- 保证 Spring bean 的调用方调用的时候 bean 是完全初始化状态
至此,Spring bean 的注入已经 初入门径了。
Field xxx in xxx.xxx.xxx.xx required a single bean, but 2 were found
@Autowired 是根据接口进行注入,上述问题是因为在 依赖查找 中发现同一 Interface 的多个实例 bean
场景还原如下
- 声明一个接口类
public interface MultiService {
}
- 添加两个实现类
@Service
public class MultiServiceImpl implements MultiService{
}
@Service
public class MMultiService implements MultiService{
}
- 注入 MultiService
@Service
public class TestService {
    //这里进行注入,然而 Spring 发现了2个实例,默认规则没有匹配上,不知道该注入哪个了
    @Autowired
    private MultiService multiService;
}
那么,在一个接口有多个实现 bean 的情况下,如何注入自己想要的 bean ?
依赖查找的部分规则
- 首先根据类型查找(byType),如果查找结果唯一,就返回给依赖赋值。
- 如果依赖不唯一,则根据名称查找(byName),bean 名称不会重复。
byName的匹配规则:
- 如果有 @Qualifier指定 依赖 bean 的名称,则拿指定名称与上述查找到的 bean 的名称进行匹配,匹配到则返回给依赖赋值
- 如果匹配不到,则拿 @Autowired修饰的字段名或者方法参数名与 上述查找到的 bean 的名称匹配,匹配到则返回给依赖赋值
- 匹配不到则报 Field xxx in xxx.xxx.xxx.xx required a single bean, but 2 were found错误
bean 名称的指定
在声明一个 bean 的时候,可以指定 bean 名称
//这里指定了bean name 为 componentService
@Component("componentService")
public class ComponentService {
}
//这里指定了bean name 为 multiService
@Service("multiService")
public class MultiServiceImpl implements MultiService{
}
//这里指定了bean name 为 mMultiService
@Service("mMultiService")
public class MMultiService implements MultiService{
}
如果没有指定 bean 名称,默认会以当前类名的首字母小写为 bean 名称
但是如果当前类的第二个字母仍然为大写,那就会以当前类名 为 bean 名称
如 MMultiService 的默认 bean 名称为 MMultiService
MultiServiceImpl  的默认 bean 名称为 multiServiceImpl
在使用一个 bean 的时候,也可以指定 bean 名称
@Service
public class TestService {
    @Autowired
    @Qualifier("MMultiService")  //指定 bean 名称
    private MultiService multiService;
}
org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'xxx' for bean class [xxx.xx.xx.xx] conflicts with existing, non-compatible bean definition of same name and class [xxx.xxx.xxx]
这种就是 bean 名称定义重复了,知道异常栈中提示的错误 bean 名称并修改即可
The bean 'xxx', defined in class path resource [xx/xx/xx.class], could not be registered. A bean with that name has already been defined in file [xx\xx\xx.class] and overriding is disabled.
这种是 bean 被声明了多次,检查是否配置类编写错误,一般业务 bean 不会声明多次
这里可能会提示你通过设置 spring.main.allow-bean-definition-overriding=true 允许 bean 定义被覆盖
Action:
Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true
请不要这么做!请找到 bean 声明冲突的地方,检查 bean 是否有特殊设置,根据业务进行取舍。不要简单覆盖 bean 定义了事
Spring常见异常说明的更多相关文章
- spring常见异常
		1.ClassNotFoundException: org.springframework.dao.support.DaoSupport(解决:导入spring-tx) 2.NoClassDefFou ... 
- spring集成Junit做单元测试及常见异常解决办法
		spring-test依赖包 <!--Spring-test --> <!-- https://mvnrepository.com/artifact/org.springframew ... 
- spring使用aop需要的jar包,和常见异常
		3.0以后spring不再一起发布aop依赖包,需要自己导入: 必须包: 这几个jar包分别为 1.org.springframework.aop-3.1.1.RELEASE 这个是spring的 ... 
- Spring学习总结(14)——Spring10种常见异常解决方法
		在程序员生涯当中,提到最多的应该就是SSH三大框架了.作为第一大框架的Spring框架,我们经常使用. 然而在使用过程中,遇到过很多的常见异常,我在这里总结一下,大家共勉. 一.找不到配置文件的异常 ... 
- 【转】Hibernate 常见异常
		转载地址:http://smartan.iteye.com/blog/1542137 Hibernate 常见异常net.sf.hibernate.MappingException 当出 ... 
- Spring10种常见异常解决方法
		在程序员生涯当中,提到最多的应该就是SSH三大框架了.作为第一大框架的Spring框架,我们经常使用. 然而在使用过程中,遇到过很多的常见异常,我在这里总结一下,大家共勉. 一.找不到配置文件的异常 ... 
- Hibernate 常见异常
		Hibernate 常见异常net.sf.hibernate.MappingException 当出现net.sf.hibernate.MappingException: Error r ... 
- Spring启动异常: cvc-elt.1: Cannot find the declaration of element 'beans'(转)
		Spring启动异常: cvc-elt.1: Cannot find the declaration of element 'beans' 2008-09-07 22:41 今天把在线聊天室代码改了下 ... 
- orcal 数据库 maven架构  ssh框架 的全xml环境模版 及常见异常解决
		创建maven项目后,毫不犹豫,超简单傻瓜式搞定dependencies(pom.xml 就是maven的依赖管理),这样你就有了所有你要的包 <project xmlns="http ... 
随机推荐
- Java注解类型(@Annotation)
			简述 注解本质是一个继承了Annotation的特殊接口,其具体实现类是Java运行时生成的动态代理类.而我们通过反射获取注解时,返回的是Java运行时生成的动态代理对象$Proxy1.通过代理对象调 ... 
- Qt 中英文切换
			一.前言 软件面向不同国籍用户时,需要显示不同语言的操作界面,Qt提供语言家可翻译为不同语言类型,方便软件走向国际化. 二.功能实现 1.翻译文件制作 1)在pro文件中添加生成中英文翻译过渡文件(. ... 
- 基于Jira的运维发布平台的设计与实现
			作者:乔克 公众号:运维开发故事 上线发布是运维的日常工作,常见的发布方式有: 手动发布 Jenkins发布平台 Gitlab CI ...... 除此之外还有需要开源软件,他们都有非常不错的发布管理 ... 
- fragment textWatcher的设置位置
			override fun onStart() { super.onStart() Log.d("------------", "1") val titleWat ... 
- 修改mysql中数据库存储主路径
			一.首先把mysql的服务先停掉. 二.更改MySQL配置文件My.ini中的数据库存储主路径 打开文件夹C:\ProgramData\MySQL\MySQL Server 5.7中的my.ini文件 ... 
- 使用adb命令在模拟器安装apk
			1.adb connect 127.0.0.1:7555 连接网易模拟器地址2.adb devices -L 查看有几个连接端口地址3.执行推送配置文件 命令 adb push 文件 路径 
- 二、Nginx 服务器升级
			1,编译新版本的nginx 软件 [root@client lnmp_soft]# tar -xf nginx-1.12.2.tar.gz -C .. [root@client lnmp_soft ... 
- 基于Typescript的Vue项目配置国际化
			基于Typescript的Vue项目配置国际化 简介 使用vue-i18n插件对基于Typescript的vue项目配置国际化,切换多种语言, 配合element-ui或者其他UI库 本文以配置中英文 ... 
- JMeter执行方式
			JMeter执行方式有2种,一种是GUI模式,一种是NO-GUI模式. GUI模式就是界面模式,如下: NO-GUI模式就是命令行模式. 界面模式主要用来编写和调试脚本用的,项目的真正执行最好是采用命 ... 
- css--常见左右盒子高度自适应布局
			前言 前端开发工程师最基础的技能要求是根据 ui 设计稿还原网页,这就缺少不了必要的网页布局,首先看下最近小伙伴问我的一个问题,他说一个网页有左右两个部分,左右两个部分的高度都不固定,要使得右部分的宽 ... 
