Spring中常见的bean创建异常

Spring中常见的bean创建异常

1. 概述 
    本次我们将讨论在spring中BeanFactory创建bean实例时经常遇到的异常 
org.springframework.beans.factory.BeanCreationException,下面我们将讨论并再现这些异常,同时给出解决方案。

2. Cause:org.springframework.beans.factory.NoSuchBeanDefinitionException 
    到目前为止最常见的导致BeanCreationException 莫过于注入一个上下文中不存在的bean。 
例如:BeanA尝试注入BeanB

@Component
public class BeanA {

    @Autowired
    private BeanB dependency;
    ...
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

如果spring上下文中不存在BeanB,那么下面的异常将会抛出

Error creating bean with name ‘beanA‘: Injection of autowired dependencies failed;
nested exception is org.springframework.beans.factory.BeanCreationException:
Could not autowire field: private org.baeldung.web.BeanB org.baeldung.web.BeanA.dependency;
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type [org.baeldung.web.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)}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

解决这种类型的问题——首先, 确保bean已经声明了 
  在XML配置文件使用< bean / >元素 
  或通过@bean注释Java @ configuration类 
  或注释:@Component,@Repository,@Service,@Controller和类路径是否扫描包中。 
同时检查配置文件或类文件是否真的已经被spring装载到上下文中。

3. Cause:org.springframework.beans.factory.NoUniqueBeanDefinitionException 
另一个比较类似的异常情况,当你尝试让spring使用接口名来时创建一个bean时,但是发现它有两个或多个实现 
例如:BeanB1 和BeanB2都实现了同一个接口

@Component
public class BeanB1 implements IBeanB { ... }
@Component
public class BeanB2 implements IBeanB { ... }

@Component
public class BeanA {

    @Autowired
    private IBeanB dependency;
    ...
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

这将导致BeanFactory抛出一下异常:

Error creating bean with name ‘beanA‘: Injection of autowired dependencies failed;
nested exception is org.springframework.beans.factory.BeanCreationException:
Could not autowire field: private org.baeldung.web.IBeanB org.baeldung.web.BeanA.b;
nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException:
No qualifying bean of type [org.baeldung.web.IBeanB] is defined:
expected single matching bean but found 2: beanB1,beanB2
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

4. Cause:org.springframework.beans.BeanInstantiationException 
4.1. Custom Exception

下面例子是抛出在其创建过程异常;简化的样例很容易体现和理解问题出现构造函数中,并抛出一个异常:

@Component
public class BeanA {

    public BeanA() {
        super();
        throw new NullPointerException();
    }
    ...
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

不出所料,spring很快的抛出以下异常:

Error creating bean with name ‘beanA‘ defined in file [...BeanA.class]:
Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException:
Could not instantiate bean class [org.baeldung.web.BeanA]:
Constructor threw exception;
nested exception is java.lang.NullPointerException
  • 1
  • 2
  • 3
  • 4
  • 5

4.2. java.lang.InstantiationException

另一种可能发生BeanInstantiationException是在xml配置中使用抽象类定义bean。 
这种只可能发生在xml配置文件中, 
因为没有办法在[email protected]文件和classpath扫描会忽略抽象类来做到这一点:

@Component
public abstract class BeanA implements IBeanA { ... }
  • 1
  • 2
<bean id="beanA" class="org.baeldung.web.BeanA" />
  • 1
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name ‘beanA‘ defined in class path resource [beansInXml.xml]:
Instantiation of bean failed;
nested exception is org.springframework.beans.BeanInstantiationException:
Could not instantiate bean class [org.baeldung.web.BeanA]:
Is it an abstract class?;
nested exception is java.lang.InstantiationException
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

4.3. java.lang.NoSuchMethodException

如果一个bean类没有默认的构造方法,spring在创建bean实例时将会抛出如下运行时异常:

@Component
public class BeanA implements IBeanA {

    public BeanA(final String name) {
        super();
        System.out.println(name);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

如果该类的类路径在扫描路径下,将会抛出如下失败:

Error creating bean with name ‘beanA‘ defined in file [...BeanA.class]: Instantiation of bean failed;
nested exception is org.springframework.beans.BeanInstantiationException:
Could not instantiate bean class [org.baeldung.web.BeanA]:
No default constructor found;
nested exception is java.lang.NoSuchMethodException: org.baeldung.web.BeanA.<init>()
  • 1
  • 2
  • 3
  • 4
  • 5

类似的异常,但难以诊断,当类路径的Spring的依赖并不具有相同的版本,可能会发生异常;这种版本不兼容,可能会导致因API变化的NoSuchMethodException。这种问题的解决方案是确保所有Spring库在该项目中的精确相同的版本。 
5. Cause:org.springframework.beans.NotWritablePropertyException 
然而,另一种可能性是你定义了一个bean:BeanA同时引用了另一个bean:BeanB但是BeanA中却没有相应的setter方法

@Component
public class BeanA {
    private IBeanB dependency;
    ...
}
@Component
public class BeanB implements IBeanB { ... }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

配置文件

<bean id="beanA" class="org.baeldung.web.BeanA">
    <property name="beanB" ref="beanB" />
</bean>
  • 1
  • 2
  • 3

此外需要说明的是,这种情况只可能发生在xml配置文件,因为当你使用@Configuration时,spring容器会避免这种情况的发生。 
当然,为了解决这个问题,需要为IBeanB添加setter方法

@Component
public class BeanA {
    private IBeanB dependency;

    public void setDependency(final IBeanB dependency) {
        this.dependency = dependency;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

6. Cause:org.springframework.beans.factory.CannotLoadBeanClassException 
当spring加载不到bean对应的类文件时,这种异常将会被抛出。这种情况很有可能发生在当配置文件中的类路径全称找不到对应文件时。

<bean id="beanZ" class="org.baeldung.web.BeanZ" />
  • 1

抛出ClassNotFoundException的根本原因

nested exception is org.springframework.beans.factory.BeanCreationException:
...
nested exception is org.springframework.beans.factory.CannotLoadBeanClassException:
Cannot find class [org.baeldung.web.BeanZ] for bean with name ‘beanZ‘
defined in class path resource [beansInXml.xml];
nested exception is java.lang.ClassNotFoundException: org.baeldung.web.BeanZ
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

7. Children of BeanCreationException 
7.1. The org.springframework.beans.factory.BeanCurrentlyInCreationException 
BeanCurrentlyInCreationException是BeanCreationException的一个子类,经常在发生在错误的使用构造方法注入bean。 
例如:循环依赖的情况

@Component
public class BeanA implements IBeanA {
    private IBeanB beanB;

    @Autowired
    public BeanA(final IBeanB beanB) {
        super();
        this.beanB = beanB;
    }
}
@Component
public class BeanB implements IBeanB {
    final IBeanA beanA;

    @Autowired
    public BeanB(final IBeanA beanA) {
        super();
        this.beanA = beanA;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

Spring将不能够解决这种场景,最终导致

org.springframework.beans.factory.BeanCurrentlyInCreationException:
Error creating bean with name ‘beanA‘:
Requested bean is currently in creation: Is there an unresolvable circular reference?
  • 1
  • 2
  • 3

完整的异常信息非常丰富

org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name ‘beanA‘ defined in file [...BeanA.class]:
Unsatisfied dependency expressed through constructor argument with index 0
of type [org.baeldung.web.IBeanB]: :
Error creating bean with name ‘beanB‘ defined in file [...BeanB.class]:
Unsatisfied dependency expressed through constructor argument with index 0
of type [org.baeldung.web.IBeanA]: :
Error creating bean with name ‘beanA‘: Requested bean is currently in creation:
Is there an unresolvable circular reference?;
nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException:
Error creating bean with name ‘beanA‘:
Requested bean is currently in creation:
Is there an unresolvable circular reference?;
nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name ‘beanB‘ defined in file [...BeanB.class]:
Unsatisfied dependency expressed through constructor argument with index 0
of type [org.baeldung.web.IBeanA]: :
Error creating bean with name ‘beanA‘:
Requested bean is currently in creation:
Is there an unresolvable circular reference?;
nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException:
Error creating bean with name ‘beanA‘:
Requested bean is currently in creation: Is there an unresolvable circular reference?
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

7.2. The org.springframework.beans.factory.BeanIsAbstractException

public abstract class BeanA implements IBeanA {
   ...
}
  • 1
  • 2
  • 3

在xml配置中声明如下:

<bean id="beanA" abstract="true" class="org.baeldung.web.BeanA" />
  • 1

现在,如果试图从spring上线文中获取BeanA实例,例如:

@Configuration
public class Config {
    @Autowired
    BeanFactory beanFactory;

    @Bean
    public BeanB beanB() {
        beanFactory.getBean("beanA");
        return new BeanB();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

将会抛出以下异常:

org.springframework.beans.factory.BeanIsAbstractException:
Error creating bean with name ‘beanA‘: Bean definition is abstract
  • 1
  • 2

全部异常栈信息:

org.springframework.beans.factory.BeanCreationException:
Error creating bean with name ‘beanB‘ defined in class path resource
[org/baeldung/spring/config/WebConfig.class]: Instantiation of bean failed;
nested exception is org.springframework.beans.factory.BeanDefinitionStoreException:
Factory method
[public org.baeldung.web.BeanB org.baeldung.spring.config.WebConfig.beanB()] threw exception;
nested exception is org.springframework.beans.factory.BeanIsAbstractException:
Error creating bean with name ‘beanA‘: Bean definition is abstract
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

8. 总结 
  最后,我们应该有一个清晰的认识:什么情况会导致什么样的BeanCreationException,同时知道如何很好的解决该问题。 
这些异常的再现实例可以在 the github project 上找到,下载后用eclipse导入即可。

时间: 2024-10-11 04:56:23

Spring中常见的bean创建异常的相关文章

spring中整合memcached,以及创建memcache的put和get方法

spring中整合memcached,以及创建memcache的put和get方法: 1:在项目中导入memcache相关的jar包 2:memcache在spring.xml的配置: 代码: 1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="

spring中自动装配bean

首先用@Component注解类: package soundsystem: import org.springframework.stereotype.Component; @Component public class TestBean{ …… } 开启组件扫描spring才能自动装配bean,创建一个@ComponentScan注解的类 package soundsystem: import org.springframework.context.annotation.componentS

在Spring中使用注解(@Scheduled)创建计划任务

Spring3中加强了注解的使用,其中计划任务也得到了增强,现在创建一个计划任务只需要两步就完成了: 创建一个Java类,添加一个无参无返回值的方法,在方法上用@Scheduled注解修饰一下: 在Spring配置文件中添加三个<task:**** />节点: 最后说明一下,第一步创建的Java类要成为Spring可管理的Bean,可以直接写在XML里,也可以@Component一下 示例如下 计划任务类: /** * com.zywang.spring.task.SpringTaskDemo

Spring中常见的设计模式——单例模式

一.单例模式的应用场景 单例模式(singleton Pattern)是指确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点.J2EE中的ServletContext,ServletContextConfig等:Spring中的ApplicationContext.数据库连接池等. 二.饿汉式单例模式 饿汉式单例模式在类加载的时候就立即初始化,并且创建单例对象.它是绝对的线程安全.在线程还没出现以前就实现了,不可能存在访问安全问题. 优点:没有增加任何锁,执行效率高,用户体验比懒汉式

C++中常见的几种异常类型

1.C++具有完善的异常捕获机制,采用try{}  catch(){}机制,这是C语言无法比拟的 2.常见的几种异常: bad_alloc:       请求分配内存失败, operator new 或者 operator new [] bad_exception: 函数异常,通常是函数运行错误,抛出的异常 bad_typeid:   类型异常,通常用typeid操作符,作用于一个NULL指针时,而该指针是带有虚函数的类,这时抛出bad_typeid异常 bad_cast:    转换异常,使用

半夜思考之查漏补缺, 在 Spring中, 所有的bean都是Spring创建的吗?

Spring 是一个 bean 容器, 负责 bean的创建, 那么所有的 bean对象都是 Spring 容器创建的吗? 答案是否定的. 但是乍一想, 好像所有的对象都是 Spring 容器负责创建并注入的, 今天在看书的时候, 看到了创建 bean 的三种方式, 分别是 : 使用构造器创建 bean实例 使用静态工厂方法创建 bean 调用实例工厂方法创建 bean 第一个是 Spring 使用反射创建 bean 对象, class属性指定的是 Bean实现类 ; 第二个的class属性指定

解决Spring中singleton的Bean依赖于prototype的Bean的问题

在spring bean的配置的时候,可能会出现一个singleton的bean依赖一个prototype的bean.因为singleton的bean只有一次初始化的机会,所以他们的依赖关系页只有在初始化的时候被设置,在这个时候同样会初始化一个prototype的bean,这样就会导致本来是prototype的bean成了singleton了,这种矛盾的解决方案有两个: 1.放弃使用依赖注入,在需要的时候主动向容器申请. 2.利用方法注入 第一种方法显然是不合理的--- 方法注入通常使用look

Spring中@Component和@Bean的区别

Spring 管理Bean的方式 Spring管理Bean分为两个部分,一个是注册Bean,一个装配Bean. 完成这两个动作有三种方式,一种是使用自动配置的方式.一种是使用JavaConfig的方式,一种就是使用XML配置的方式. @Component 把普通pojo实例化到spring容器中 @Bean 需要在配置类中使用,即类上需要加上@Configuration注解 两者都能通过@Autowired注解自动装配 @Compent和@Bean到底区别在哪? 在应用开发的过程中,如果想要将第

Spring中常见的设计模式——装饰者模式

一.装饰者模式的应用场景 装饰者模式(Decorator Pattern)是指在不改变原有对象的基础上,将功能附加到对象上,提供了比继承更有弹性的方案(扩展原有对象的功能),属于结构型模式.装饰者模式适用于以下场景: 扩展一个类的功能或给一个类添加附加职责. 动态给一个对象天机功能,这些功能可以再动态的撤销. 以做煎饼果子为例演示装饰者模式是怎么装的: 首先做一个煎饼果子抽象: public abstract class Battercake { protected abstract Strin