• Spring中常见的bean创建异常


    Spring中常见的bean创建异常

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

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

    @Component
    public class BeanA {
    
        @Autowired
        private BeanB dependency;
        ...
    }

    如果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)}

      解决这种类型的问题——首先, 确保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;
        ...
      }

      这将导致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

    4. Cause:org.springframework.beans.BeanInstantiationException

    4.1. Custom Exception

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

    @Component
    public class BeanA {
    
        public BeanA() {
            super();
            throw new NullPointerException();
        }
        ...
    }

     不出所料,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

    4.2. java.lang.InstantiationException

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

    @Component
    public abstract class BeanA implements IBeanA { ... }
    <bean id="beanA" class="org.baeldung.web.BeanA" />
    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

    4.3. java.lang.NoSuchMethodException

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

    @Component
    public class BeanA implements IBeanA {
    
        public BeanA(final String name) {
            super();
            System.out.println(name);
        }
    }

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

    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>()

    类似的异常,但难以诊断,当类路径的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 { ... }

    配置文件

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

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

    @Component
    public class BeanA {
        private IBeanB dependency;
    
        public void setDependency(final IBeanB dependency) {
            this.dependency = dependency;
        }
    }

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

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

    抛出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
    

    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;
        }
    }

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

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

    完整的异常信息非常丰富

    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?

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

    public abstract class BeanA implements IBeanA {
       ...
    }

    在xml配置中声明如下:

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

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

    @Configuration
    public class Config {
        @Autowired
        BeanFactory beanFactory;
    
        @Bean
        public BeanB beanB() {
            beanFactory.getBean("beanA");
            return new BeanB();
        }
    }

    将会抛出以下异常:

    org.springframework.beans.factory.BeanIsAbstractException: 
    Error creating bean with name 'beanA': Bean definition is abstract

    部异常栈信息

    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

    8、org.springframework.beans.factory.BeanNotOfRequiredTypeException
    由于我之前在实现Dao接口时直接实现了Dao的实现类DaoImpl而不是实现Dao,所以当另一个类实现Dao接口时则会出现异常。
    所以下次要使用Dao接口来注入而不是具体的实现类。

  • 相关阅读:
    微信小程序promise解决onload异步
    小程序中使用 Less (VScode)
    Vue中使用less
    小程序获取 图片宽高
    ssh 登录出现Are you sure you want to continue connecting (yes/no)?解决方法
    SQL SERVER 收缩日志
    SQL SERVER-日期时间
    oracle判断查询结果是否为空
    修改Tomcat默认JDK版本
    Microsoft SQL Server Management Studio ------- 附加数据库 对于 服务器“xxx&amp;amp;quot;失败(错误码5120)
  • 原文地址:https://www.cnblogs.com/hggen/p/6254136.html
Copyright © 2020-2023  润新知