Spring BeanCreationException
1. 概要
この記事では、Spring org.springframework.beans.factory.BeanCreationExceptionについて説明します。これは、BeanFactoryがBean定義のBeanを作成し、問題が発生したときにスローされる非常に一般的な例外です。 この記事では、この例外の最も一般的な原因と解決策について説明します。
参考文献:
Springでの制御の反転と依存性注入の概要
Inversion of Control and Dependency Injectionの概念の簡単な紹介に続いて、Spring Frameworkを使用した簡単なデモンストレーション
SpringのBeanNameAwareおよびBeanFactoryAwareインターフェース
SpringのBeanNameAwareおよびBeanFactoryAwareインターフェースの操作をご覧ください。
2. 原因:org.springframework.beans.factory.NoSuchBeanDefinitionException
BeanCreationExceptionの最も一般的な原因は、Springがコンテキスト内でinject a bean that doesn’t existを試行することです。
たとえば、BeanAはBeanBを注入しようとしています。
@Component
public class BeanA {
@Autowired
private BeanB dependency;
...
}
コンテキストでBeanBが見つからない場合、次の例外がスローされます(Beanの作成エラー)。
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.example.web.BeanB org.example.web.BeanA.dependency;
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type [org.example.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が宣言されていることを確認します。
-
<bean />要素を使用するXML構成ファイルのいずれか
-
または、@Beanアノテーションを介したJava@Configurationクラス
-
または、@Component、@Repository、@Service、@Controllerの注釈が付けられ、そのパッケージに対してクラスパススキャンがアクティブになっています
また、構成ファイルまたはクラスが実際にSpringによって取得され、メインコンテキストに読み込まれていることを確認します。
参考文献:
Springでの制御の反転と依存性注入の概要
Inversion of Control and Dependency Injectionの概念の簡単な紹介に続いて、Spring Frameworkを使用した簡単なデモンストレーション
SpringのBeanNameAwareおよびBeanFactoryAwareインターフェース
SpringのBeanNameAwareおよびBeanFactoryAwareインターフェースの操作をご覧ください。
3. 原因:org.springframework.beans.factory.NoUniqueBeanDefinitionException
Bean作成例外のもう1つの同様の原因は、Springがタイプ別に(つまり、そのインターフェースによって)Beanを注入しようとし、コンテキスト内でtwo or more bean implementing that interfaceを見つけようとしていることです。
たとえば、BeanB1とBeanB2はどちらも同じインターフェイスを実装しています。
@Component
public class BeanB1 implements IBeanB { ... }
@Component
public class BeanB2 implements IBeanB { ... }
@Component
public class BeanA {
@Autowired
private IBeanB dependency;
...
}
これにより、Spring Beanファクトリによって次の例外がスローされます。
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.example.web.IBeanB org.example.web.BeanA.b;
nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException:
No qualifying bean of type [org.example.web.IBeanB] is defined:
expected single matching bean but found 2: beanB1,beanB2
4. 原因:org.springframework.beans.BeanInstantiationException
4.1. カスタム例外
次の行はbean that throws an exception during its creation processです。問題を簡単に例示して理解するための単純化されたサンプルは、Beanのコンストラクターで例外をスローしています。
@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.example.web.BeanA]:
Constructor threw exception;
nested exception is java.lang.NullPointerException
4.2. java.lang.InstantiationException
BeanInstantiationExceptionのもう1つの考えられる発生は、抽象クラスをXMLのBeanとして定義することです。 Java @Configurationファイルでこれを行う方法はなく、クラスパススキャンは抽象クラスを無視するため、これはXMLである必要があります。
@Component
public abstract class BeanA implements IBeanA { ... }
そして、BeanのXML定義:
このセットアップでは、同様の例外が発生します。
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.example.web.BeanA]:
Is it an abstract class?;
nested exception is java.lang.InstantiationException
4.3. java.lang.NoSuchMethodException
Beanにデフォルトコンストラクターがなく、Springがそのコンストラクターを探してインスタンス化しようとすると、実行時例外が発生します。例えば:
@Component
public class BeanA implements IBeanA {
public BeanA(final String name) {
super();
System.out.println(name);
}
}
このBeanがクラスパススキャンメカニズムによって取得されると、障害は次のようになります。
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.example.web.BeanA]:
No default constructor found;
nested exception is java.lang.NoSuchMethodException: org.example.web.BeanA.()
クラスパスへのSpringの依存関係にsame versionがない場合、同様の例外が発生する可能性がありますが、診断が困難です。この種のバージョンの非互換性により、APIの変更によりNoSuchMethodExceptionが発生する可能性があります。 このような問題の解決策は、すべてのSpringライブラリがプロジェクト内でまったく同じバージョンであることを確認することです。
5. 原因:org.springframework.beans.NotWritablePropertyException
さらに別の可能性は、BeanAに対応するセッターメソッドがなくても、別のBean –BeanB –を参照してBean –BeanA –を定義することです。
@Component
public class BeanA {
private IBeanB dependency;
...
}
@Component
public class BeanB implements IBeanB { ... }
そして、Spring XML設定:
繰り返しますが、このcan only occur in XML Configurationは、Java@Configurationを使用すると、コンパイラーがこの問題を再現できなくなるためです。
もちろん、この問題を解決するには、IBeanBにセッターを追加する必要があります。
@Component
public class BeanA {
private IBeanB dependency;
public void setDependency(final IBeanB dependency) {
this.dependency = dependency;
}
}
6. 原因:org.springframework.beans.factory.CannotLoadBeanClassException
この例外は、Spring cannot load the class of the defined beanの場合にスローされます。これは、SpringXML構成に対応するクラスがないBeanが含まれている場合に発生する可能性があります。 たとえば、クラスBeanZが存在しない場合、次の定義は例外になります。
ClassNotFoundExceptionの場合の根本原因と、この場合の完全な例外は次のとおりです。
nested exception is org.springframework.beans.factory.BeanCreationException:
...
nested exception is org.springframework.beans.factory.CannotLoadBeanClassException:
Cannot find class [org.example.web.BeanZ] for bean with name 'beanZ'
defined in class path resource [beansInXml.xml];
nested exception is java.lang.ClassNotFoundException: org.example.web.BeanZ
7. BeanCreationExceptionの子
7.1. org.springframework.beans.factory.BeanCurrentlyInCreationException
BeanCreationExceptionのサブクラスの1つはBeanCurrentlyInCreationExceptionです。これは通常、コンストラクタインジェクションを使用する場合に発生します。たとえば、循環依存の場合です。
@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.example.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.example.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.example.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. org.springframework.beans.factory.BeanIsAbstractException
このインスタンス化の例外は、Beanファクトリが抽象として宣言されたBeanを取得してインスタンス化しようとしたときに発生する可能性があります。例えば:
public abstract class BeanA implements IBeanA {
...
}
XML構成で次のように宣言されています。
ここで、retrieve BeanA from the Spring Context by nameを実行しようとすると、たとえば、別のBeanをインスタンス化する場合:
@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/example/spring/config/WebConfig.class]: Instantiation of bean failed;
nested exception is org.springframework.beans.factory.BeanDefinitionStoreException:
Factory method
[public org.example.web.BeanB org.example.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. 結論
この記事の最後に、SpringでBeanCreationExceptionにつながる可能性のあるさまざまな原因と問題をナビゲートするための明確なマップと、これらすべての問題を修正する方法を十分に把握する必要があります。
すべての例外の例の実装はthe github projectにあります。これはEclipseベースのプロジェクトであるため、そのままインポートして実行するのは簡単です。