Springコンポーネントスキャニング

1概要

このチュートリアルでは、Springでのコンポーネントスキャンについて説明します。 Springで作業するときは、クラスをSpring Beanにするためにクラスに注釈を付けることができます。しかし、それ以外にも、これらのアノテーション付きクラスを検索する場所をSpringに指示することができます。** この特定の実行ではすべてがBeanになる必要はないためです。

もちろん、コンポーネントスキャンにはデフォルト値がいくつかありますが、検索用にパッケージをカスタマイズすることもできます。

まず、デフォルト設定を見てみましょう。

2引数なしの @ ComponentScan

2.1. Springアプリケーションで @ ComponentScan を使用する

Springでは、スキャンしたいパッケージを指定するために @ Configuration アノテーションとともに @ ComponentScan アノテーションを使用します。引数なしの @ ComponentScan は、現在のパッケージとそのすべてのサブパッケージをスキャンするようにSpringに指示します。

com.baeldung.componentscan.springapp パッケージに次の @ Configuration があるとします。

@Configuration
@ComponentScan
public class SpringComponentScanApp {
    private static ApplicationContext applicationContext;

    @Bean
    public ExampleBean exampleBean() {
        return new ExampleBean();
    }

    public static void main(String[]args) {
        applicationContext = new AnnotationConfigApplicationContext(SpringComponentScanApp.class);

        for (String beanName : applicationContext.getBeanDefinitionNames()) {
            System.out.println(beanName);
        }
    }
}

また、 com.baeldung.componentscan.springapp.animals パッケージに Cat コンポーネントと Dog コンポーネントがあるとします。

package com.baeldung.componentscan.springapp.animals;//...
@Component
public class Cat {}
package com.baeldung.componentscan.springapp.animals;//...
@Component
public class Dog {}

そして最後に、 com.baeldung.componentscan.springapp.flowers パッケージに Rose コンポーネントがあります。

package com.baeldung.componentscan.springapp.flowers;//...
@Component
public class Rose {}

main() メソッドの出力には、 com.baeldung.componentscan.springapp パッケージおよびそのサブパッケージのすべてのBeanが含まれます。

springComponentScanApp
cat
dog
rose
exampleBean

メインアプリケーションクラスは、 @ Configuration、つまり @ Component__でアノテーションが付けられているので、Beanでもあることに注意してください。

また、メインアプリケーションクラスと設定クラスは必ずしも同じではありません。異なる場合は、メインアプリケーションクラスをどこに配置するかは重要ではありません。 ** デフォルトではコンポーネントのスキャンがそのパッケージから開始されるため、構成クラスの場所だけが問題になります。

最後に、この例では @ ComponentScan は次のものと同等です。

@ComponentScan(basePackages = "com.baeldung.componentscan.springapp")

basePackages 引数は、スキャン対象のパッケージまたはパッケージの配列です。

2.2. Spring Bootアプリケーションで @ ComponentScan を使用する

Spring Bootのトリックは、多くのことが暗黙的に起こるということです。私たちは @ SpringBootApplication アノテーションを使っていますが、それは3つのアノテーションの組み合わせです

@Configuration
@EnableAutoConfiguration
@ComponentScan

com.baeldung.componentscan.springbootapp パッケージにも同様の構造を作成しましょう。今回の主なアプリケーションは次のようになります。

package com.baeldung.componentscan.springbootapp;//...
@SpringBootApplication
public class SpringBootComponentScanApp {
    private static ApplicationContext applicationContext;

    @Bean
    public ExampleBean exampleBean() {
        return new ExampleBean();
    }

    public static void main(String[]args) {
        applicationContext = SpringApplication.run(SpringBootComponentScanApp.class, args);
        checkBeansPresence("cat", "dog", "rose", "exampleBean", "springBootComponentScanApp");

    }

    private static void checkBeansPresence(String... beans) {
        for (String beanName : beans) {
            System.out.println("Is " + beanName + " in ApplicationContext: " +
              applicationContext.containsBean(beanName));
        }
    }
}

他のすべてのパッケージとクラスは同じままです。近くの com.baeldung.componentscan.springbootapp パッケージにコピーするだけです。

Spring Bootは前の例と同様にパッケージをスキャンします。出力を確認しましょう。

Is cat in ApplicationContext: true
Is dog in ApplicationContext: true
Is rose in ApplicationContext: true
Is exampleBean in ApplicationContext: true
Is springBootComponentScanApp in ApplicationContext: true

2番目の例でBeanの存在をチェックしているのは、出力が大きすぎるためです。

これは、Spring Bootが pom.xmlファイルの依存関係に依存して自動的に多くのBeanを作成するようにする、暗黙の @ EnableAutoConfiguration__アノテーションのためです。

3 @ ComponentScan 引数付き

それではスキャンのパスをカスタマイズしましょう。たとえば、 Rose Beanを除外したいとしましょう。

いくつかの方法でそれを行うことができます。まず、基本パッケージを変更します。

@ComponentScan(basePackages = "com.baeldung.componentscan.springapp.animals")
@Configuration
public class SpringComponentScanApp {
  //...
}

出力は次のようになります。

springComponentScanApp
cat
dog
exampleBean

この背後にあるものを見てみましょう:

  • springComponentScanApp は、次のように渡された設定であるため作成されます。

AnnotationConfigApplicationContext への引数 ** exampleBean は、設定内で設定されたBeanです。

  • cat dog は指定された中にあります

com.baeldung.componentscan.springapp.animals パッケージ

もう1つの方法は、除外するクラスのパターンを指定してフィルタを使用することです。

@ComponentScan(excludeFilters =
  @ComponentScan.Filter(type=FilterType.REGEX,
    pattern="com\\.baeldung\\.componentscan\\.springapp\\.flowers\\..** "))

また、別の種類のフィルタを使用することもできます。

@ComponentScan(excludeFilters =
  @ComponentScan.Filter(type = FilterType.ASSIGNABLE__TYPE, value = Rose.class))

上記のカスタマイズはすべてSpring Bootにも適用できます。 @ ComponentScan @ SpringBootApplication と一緒に使用すると、結果は同じになります。

@SpringBootApplication
@ComponentScan(basePackages = "com.baeldung.componentscan.springbootapp.animals")

4デフォルトパッケージ

@ Configuration クラスhttps://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-structuring-your-code.htmlをデフォルトのパッケージに入れないでパッケージをまったく指定しないことによって)。この場合、Springはクラスパス内のすべてのjar内のすべてのクラスをスキャンします。これはエラーの原因となり、おそらくアプリケーションは起動しません。

5結論

この記事では、Springがデフォルトでスキャンするパッケージと、これらのパスをカスタマイズする方法を学びました。

いつものように、完全なコードはhttps://github.com/eugenp/tutorials/tree/master/spring-boot[over on GitHub]から入手できます。

前の投稿:Java NIO2非同期チャネルAPIの手引き
次の投稿:Spring Webコンテキスト