1. 概要

このチュートリアルでは、 Spring @Importアノテーションの使用方法を学び、@ ComponentScan。との違いを明確にします。

2. 構成とBean

@Import アノテーションを理解する前に、Spring Beanとは何かを理解し、@ Configurationアノテーションの基本的な実用知識を持っている必要があります。

どちらのトピックも、このチュートリアルの範囲外です。 それでも、SpringBeanの記事Springのドキュメントでそれらについて学ぶことができます。

Bird、Cat、Dog の3つのBeanが、それぞれ独自の構成クラスですでに準備されていると仮定します

次に、これらのConfigクラスを使用してコンテキストを提供できます。

@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = { BirdConfig.class, CatConfig.class, DogConfig.class })
class ConfigUnitTest {

    @Autowired
    ApplicationContext context;

    @Test
    void givenImportedBeans_whenGettingEach_shallFindIt() {
        assertThatBeanExists("dog", Dog.class);
        assertThatBeanExists("cat", Cat.class);
        assertThatBeanExists("bird", Bird.class);
    }

    private void assertThatBeanExists(String beanName, Class<?> beanClass) {
        Assertions.assertTrue(context.containsBean(beanName));
        Assertions.assertNotNull(context.getBean(beanClass));
    }
}

3. @Importを使用した構成のグループ化

すべての構成を宣言することに問題はありません。 しかし、は、さまざまなソース内の数十の構成クラスを制御する際の問題を想像してみてください。 より良い方法があるはずです。

@ Import アノテーションには、Configurationクラスをグループ化する機能による解決策があります。

@Configuration
@Import({ DogConfig.class, CatConfig.class })
class MammalConfiguration {
}

ここで、哺乳類を覚えておく必要があります。

@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = { MammalConfiguration.class })
class ConfigUnitTest {

    @Autowired
    ApplicationContext context;

    @Test
    void givenImportedBeans_whenGettingEach_shallFindOnlyTheImportedBeans() {
        assertThatBeanExists("dog", Dog.class);
        assertThatBeanExists("cat", Cat.class);

        Assertions.assertFalse(context.containsBean("bird"));
    }

    private void assertThatBeanExists(String beanName, Class<?> beanClass) {
        Assertions.assertTrue(context.containsBean(beanName));
        Assertions.assertNotNull(context.getBean(beanClass));
    }
}

まあ、おそらくすぐに Bird を忘れてしまうので、もう1つのグループを実行して、すべての動物構成クラスを含めましょう。

@Configuration
@Import({ MammalConfiguration.class, BirdConfig.class })
class AnimalConfiguration {
}

最後に、誰も取り残されませんでした。1つのクラスを覚えておく必要があります。

@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = { AnimalConfiguration.class })
class AnimalConfigUnitTest {
    // same test validating that all beans are available in the context
}

4. @Import@ComponentScan

@ Import の例に進む前に、簡単に停止して、@ComponentScanと比較してみましょう。

4.1. 類似点

どちらのアノテーションも、@Componentまたは@Configurationクラスを受け入れることができます。

@ Import を使用して、新しい@ Componentを追加しましょう。

@Configuration
@Import(Bug.class)
class BugConfig {
}

@Component(value = "bug")
class Bug {
}

現在、 Bug Beanは、他のBeanと同じように使用できます。

4.2. 概念の違い

簡単に言えば、両方の注釈で同じ結果に到達できます。 それで、それらの間に何か違いはありますか?

この質問に答えるために、Springは一般的に設定より規約アプローチを促進することを思い出してください。

私たちの注釈とのアナロジーを作る、 @ ComponentScan は慣例に似ていますが、@ Importは構成に似ています.

4.3. 実際のアプリケーションで何が起こるか

通常、ルートパッケージの@ComponentScanを使用してアプリケーションを起動し、すべてのコンポーネントを検索できるようにします。 Spring Bootを使用している場合、 @ SpringBootApplicationにはすでに@ComponentScanが含まれているので、準備は完了です。 これは、慣習の力を示しています。

ここで、アプリケーションが大幅に成長していると想像してみましょう。 ここで、コンポーネント、さまざまなパッケージ構造、自分自身やサードパーティによって構築されたモジュールなど、さまざまな場所からのBeanを処理する必要があります。 

この場合、コンテキストにすべてを追加すると、使用するBeanについて競合が発生するリスクがあります。 それに加えて、起動時間が遅くなる可能性があります。

一方、は、逆効果であるため、新しいコンポーネントごとに@Importを記述したくありません。

私たちの動物を例にとってみましょう。 確かに、コンテキスト宣言からインポートを非表示にすることはできますが、Configクラスごとに@Importを覚えておく必要があります。

4.4. 一緒に働いている

私たちは両方の長所を目指すことができます。 動物専用のパッケージがあることを想像してみましょう。 コンポーネントまたはモジュールであり、同じ考えを維持することもできます。

次に、動物パッケージ専用に@ComponentScanを1つ持つことができます。

package com.baeldung.importannotation.animal;

// imports...

@Configuration
@ComponentScan
public class AnimalScanConfiguration {
}

また、 @Import to は、コンテキストにを追加する内容を制御し続けます。

package com.baeldung.importannotation.zoo;

// imports...

@Configuration
@Import(AnimalScanConfiguration.class)
class ZooApplication {
}

最後に、動物パッケージに追加された新しいBeanは、コンテキストによって自動的に検出されます。 また、使用している構成を明示的に制御できます。

5. 結論

このクイックチュートリアルでは、@Importを使用して構成を整理する方法を学びました。

@Importは@ComponentScanと非常に似ていることも学びました。ただし、 @Importには明示的なアプローチがあり、@ComponentScanは暗黙的なもの

また、実際のアプリケーションで構成を制御する際に発生する可能性のある問題と、両方の注釈を組み合わせてこれらを処理する方法についても検討しました。

いつものように、完全なコードはGitHubから入手できます。