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接口來注入而不是具體的實現類。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM