SpringでのgetBean()の理解

1. 前書き

このチュートリアルでは、_BeanFactory.getBean()_メソッドのさまざまなバリアントを見ていきます。
簡単に言えば、メソッドの名前からもわかるように、* this * * SpringコンテナからBeanインスタンスを取得する責任があります*。

2. Spring Beanの設定

最初に、テスト用にいくつかのSpring Beanを定義しましょう。 SpringコンテナのBean定義を提供する方法はいくつかありますが、この例では、注釈ベースのJava構成を使用します。
@Configuration
class AnnotationConfig {

    @Bean(name = {"tiger", "kitty"})
    @Scope(value = "prototype")
    Tiger getTiger(String name) {
        return new Tiger(name);
    }

    @Bean(name = "lion")
    Lion getLion() {
        return new Lion("Hardcoded lion name");
    }

    interface Animal {}
}
2つのBeanを作成しました。 _Lion_にはデフォルトのシングルトンスコープがあります。 _Tiger_は明示的にlink:/spring-bean-scopes [プロトタイプスコープ]に設定されます。 さらに、今後のリクエストで使用する各Beanの名前を定義したことに注意してください。

3. getBean() API

link:/spring-beanfactory[_BeanFactory_]は、以下のサブセクションで検証する_getBean()_メソッドの5つの異なるシグネチャを提供します。

3.1. 名前によるBeanの取得

名前を使用して_Lion_ Beanインスタンスを取得する方法を見てみましょう。
Object lion = context.getBean("lion");

assertEquals(Lion.class, lion.getClass());
このバリアントでは、名前を指定し、代わりに、指定された名前のBeanがアプリケーションコンテキストに存在する場合に__Object __classのインスタンスを取得します。 それ以外の場合、Beanの検索が失敗すると、この実装と他のすべての実装の両方がlink:/spring-nosuchbeandefinitionexception[_NoSuchBeanDefinitionException_]をスローします。
主な欠点は、Beanを取得した後、https://www.baeldung.com/java-type-casting [目的の型にキャスト]する必要があることです。 これにより、別の例外が発生する可能性があります* *返されたBeanのタイプが予想と異なる場合*。
名前_“ lion”を使用して_Tiger_を取得しようとするとします。_result結果を_Tiger_にキャストすると、_ClassCastException_がスローされます。
assertThrows(ClassCastException.class, () -> {
    Tiger tiger = (Tiger) context.getBean("lion");
});

3.2. 名前とタイプによるBeanの取得

ここでは、要求されたBeanの名前とタイプの両方を指定する必要があります。
Lion lion = context.getBean("lion", Lion.class);
前の方法と比較して、これは型の不一致に関する情報を即座に取得するため、より安全です。
assertThrows(BeanNotOfRequiredTypeException.class, () ->
    context.getBean("lion", Tiger.class));
}

3.3. タイプによるBeanの取得

_getBean()、_の3番目のバリアントでは、Beanタイプのみを指定するだけで十分です。
Lion lion = context.getBean(Lion.class);
この場合、潜在的に曖昧な結果に特別な注意を払う必要があります*:
assertThrows(NoUniqueBeanDefinitionException.class, () ->
    context.getBean(Animal.class));
}
上記の例では、_Lion_と_Tiger_の両方が_Animal_インターフェースを実装しているため、タイプを指定するだけでは結果を明確に決定するのに十分ではありません。 したがって、_NoUniqueBeanDefinitionException_が発生します。

3.4. コンストラクターパラメーターを使用した名前によるBeanの取得

Bean名に加えて、コンストラクターパラメーターも渡すことができます。
Tiger tiger = (Tiger) context.getBean("tiger", "Siberian");
*このメソッドは、プロトタイプスコープを持つBeanにのみ適用されるため、少し異なります*。
シングルトンの場合、_https://www.baeldung.com/spring-beandefinitionstoreexception [BeanDefinitionStoreException] ._を取得します。
プロトタイプBeanは、アプリケーションコンテナからリクエストされるたびに新しく作成されたインスタンスを返すため、_getBean()_を呼び出すときに、コンストラクタパラメータをオンザフライで提供できます。
Tiger tiger = (Tiger) context.getBean("tiger", "Siberian");
Tiger secondTiger = (Tiger) context.getBean("tiger", "Striped");

assertEquals("Siberian", tiger.getName());
assertEquals("Striped", secondTiger.getName());
ご覧のとおり、各_Tiger_は、Beanを要求するときに2番目のパラメーターとして指定したものに応じて異なる名前を取得します。

3.5. コンストラクターパラメーターを使用したタイプごとのBeanの取得

このメソッドは最後のメソッドに似ていますが、名前の代わりに型を最初の引数として渡す必要があります。
Tiger tiger = context.getBean(Tiger.class, "Shere Khan");

assertEquals("Shere Khan", tiger.getName());
コンストラクターパラメーターを使用してBeanを名前で取得するのと同様に、*このメソッドはプロトタイプスコープのBeanにのみ適用されます*。

4. 使用上の考慮事項

_BeanFactory_インターフェースで定義されているにもかかわらず、_getBean()_メソッドは_ApplicationContextを介して最も頻繁にアクセスされます。通常、*プログラムで_getBean()_メソッドを直接使用したくない*
Beanはコンテナで管理する必要があります。 それらのいずれかを使用する場合は、_ApplicationContext.getBean()を直接呼び出すのではなく、https://www.baeldung.com/spring-dependency-injection [dependency injection]に依存する必要があります。アプリケーションロジックとフレームワーク関連の詳細を混在させないでください。

5. 結論

このクイックチュートリアルでは、_BeanFactory_インターフェイスから__getBean()__methodのすべての実装を確認し、それぞれの長所と短所について説明しました。
ここに示されているすべてのコード例は、https://github.com/eugenp/tutorials/tree/master/spring-core-2 [GitHub上]で入手できます。