谈谈 NoSuchBeanDefinitionException
来源:互联网 发布:垂衣女土冬天淘宝网 编辑:程序博客网 时间:2024/06/05 07:15
概述
org.springframework.beans.factory.NoSuchBeanDefinitionException
是很常见的异常,可以说绝大多数使用过 Spring 的人都曾遇到过它。本文旨在总结下NoSuchBeanDefinitionException(以下简称 NSBDE)的含义,哪些情况下可能抛出 NSBDE,和如何解决(文中配置均用 JavaConfig)。
什么是 NoSuchBeanDefinitionException
从字面其实就很好理解,NoSuchBeanDefinitionException 就是没有找到指定 Bean 的 Definition。NoSuchBeanDefinitionException 的 JavaDoc是这样定义的:
Exception thrown when a BeanFactory is asked for a bean instance for which it cannot find a definition. This may point to a non-existing bean, a non-unique bean, or a manually registered singleton instance without an associated bean definition.
下面看看可能抛出 NSBDE 的一些情况。
情况1: No qualifying bean of type […] found for dependency
最常见的抛出 NSBDE 的情况就是在一个 BeanA 中注入 BeanB 时找不到 BeanB 的定义。例子如下:
123456
public class BeanA { private BeanB dependency; //...}
当在 BeanA 中注入 BeanB 时,如果在 Spring 上下文中找不到 BeanB 的定义,就会抛出 NSBDE。异常信息如下:
1234567
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.baeldung.packageB.BeanB] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
抛异常的原因在异常信息中说的很清楚:expected at least 1 bean which qualifies as autowire candidate for this dependency
。所以要么是 BeanB 不存在在 Spring 上下文中(比如没有标注 @ Component,@Repository,@Service, @Controller等注解) ,要么就是 BeanB 所在的包没有被 Spring 扫描到。
解决办法就是先确认 BeanB 有没有被某些注解声明为 Bean:
123
package org.baeldung.packageB;public class BeanB { ...}
如果 BeanB 已经被声明为一个 Bean,就再确认 BeanB 所在的包有没有被扫描。
1234
"org.baeldung.packageB") (public class ContextWithJavaConfig {}
情况2: No qualifying bean of type […] is defined
还有一种可能抛出 NSBDE 的情况是在上下文中存在着两个 Bean,比如有一个接口 IBeanB,它有两个实现类 BeanB1 和 BeanB2。
12345678
public class BeanB1 implements IBeanB { //}public class BeanB2 implements IBeanB { //}
现在,如果 BeanA 按照下面的方式注入,那么 Spring 将不知道要注入两个实现中的哪一个,就会抛出 NSBDE。
12345
public class BeanA { private IBeanB dependency;}
异常信息如下:
1234
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [org.baeldung.packageB.IBeanB] is defined: expected single matching bean but found 2: beanB1,beanB2
仔细看异常信息会发现,并不是直接抛出 NSBDE,而是它的子类 NoUniqueBeanDefinitionException
,这是 Spring 3.2.1 之后引入的新异常,目的就是为了和第一种找不到 Bean Definition 的情况作区分。
解决办法1就是利用 @Qualifier
注解,明确指定要注入的 Bean 的名字(BeanB2 默认的名字就是 beanB2)。
123456
public class BeanA { "beanB2") ( private IBeanB dependency;}
除了指定名字,我们还可以将其中一个 Bean 加上 @Primary
的注解,这样会选择加了 Primary 注解的 Bean 来注入,而不会抛异常:
12345
public class BeanB1 implements IBeanB { //}
这样 Spring 就能够知道到底应该注入哪个 Bean 了。
情况3: No Bean Named […] is defined
NSBDE 还可能在从 Spring 上下文中通过名字获取一个 Bean 时抛出。
123456789
public class BeanA implements InitializingBean { private ApplicationContext context; public void afterPropertiesSet() { context.getBean("someBeanName"); }}
在这种情况中,如果找不到指定名字 Bean 的 Definition,就会抛出如下异常:
12
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'someBeanName' is defined
情况4: 代理 Beans
Spring 通过 AOP 代理 实现了许多高级功能,比如:
- 通过 @Transactional完成 事务管理
- 通过 @Cacheable实现缓存
- 通过 @Async和 @Scheduled实现任务调度和异步执行
Spring 有两种方式实现代理:
- 利用 JDK 动态代理机制 ,在运行时为
实现了某些接口
的类动态创建一个实现了同样接口的代理对象。 - 使用 CGLIB,CGLIB 可以在运行期扩展Java类与实现Java接口,也就是说当一个类没有实现接口时,必须用 CGLIB 生成代理对象。
所以,当 Spring 上下文中的一个实现了某个接口的 Bean 通过JDK 动态代理机制被代理时,代理类并不是继承了目标类,而是实现同样的接口。
也正因为如此,如果一个 Bean 通过接口注入时,可以成功被注入。但如果是通过真正的类注入,那么 Spring 将无法找到匹配这个类的 Definition——因为代理类并没有继承这个类。
以 Spring 中比较常见的事务管理为例,假设 ServiceA 中要注入 ServiceB,两个 Service 均标注了 @Transactional
注解来进行事务管理,那么下面的注入方式是不会正常 work 的。
123456789101112
public class ServiceA implements IServiceA{ private ServiceB serviceB; ...} public class ServiceB implements IServiceB{}
解决办法就是通过接口来进行注入:
1234567891011
public class ServiceA implements IServiceA{ private IServiceB serviceB;} public class ServiceB implements IServiceB{}
- 谈谈 NoSuchBeanDefinitionException
- NoSuchBeanDefinitionException
- NoSuchBeanDefinitionException
- NoSuchBeanDefinitionException
- spring NoSuchBeanDefinitionException
- Spring NoSuchBeanDefinitionException
- factory.NoSuchBeanDefinitionException 异常
- Spring NoSuchBeanDefinitionException原因分析
- spring 报错:.NoSuchBeanDefinitionException
- nosuchbeandefinitionexception 注入失败
- Spring NoSuchBeanDefinitionException原因分析
- Spring 报 NoSuchBeanDefinitionException
- Spring 报 NoSuchBeanDefinitionException
- spring mybatis NoSuchBeanDefinitionException 解决方案
- mybatis NoSuchBeanDefinitionException 解决方案
- 谈谈
- 谈谈~~
- 谈谈
- 【第十三课】StringBuffer的使用
- Butterknife使用文档
- spring检查bean name唯一性
- Java中private、protected、public和default的区别
- java-封装
- 谈谈 NoSuchBeanDefinitionException
- C语言宏定义的几个坑和特殊用法
- iOS项目工程中创建静态库文件(.a)库文件
- Javascript中构造函数与new命令
- 工作十年,我是如何达到年薪40W以上
- Java 异常处理
- Linux常用命令
- 深入剖析c++动态内存管理
- mac上idea出现tomcat端口占用问题