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

スプリングコンポーネントスキャン

1. 概要

このチュートリアルでは、Springでのコンポーネントスキャンについて説明します。 Springで作業する場合、Spring Beanにするためにクラスに注釈を付けることができます。 ただし、それ以外に、we can tell Spring where to search for these annotated classesは、この特定の実行ですべてがBeanになる必要はないためです。

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

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

2. 引数なしの@ComponentScan

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

Springの場合、we use the @ComponentScan annotation along with @Configuration annotation to specify the packages that we want to be scanned。 引数のない@ComponentScanは、現在のパッケージとそのすべてのサブパッケージをスキャンするようにSpringに指示します。

com.example.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.example.componentscan.springapp.animalsパッケージにCatコンポーネントとDogコンポーネントがあるとします。

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

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

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

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

springComponentScanApp
cat
dog
rose
exampleBean

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

また、メインアプリケーションクラスと構成クラスは必ずしも同じではないことに注意してください。 それらが異なる場合は、メインアプリケーションクラスをどこに配置するかは問題ではありません。 Only the location of the configuration class matters as component scanning starts from its package by default

最後に、この例では、@ComponentScanは次と同等であることに注意してください。

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

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

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

Spring Bootのコツは、多くのことが暗黙的に発生することです。 @SpringBootApplicationアノテーションを使用しますが、これは3つのアノテーションの組み合わせにすぎません。

@Configuration
@EnableAutoConfiguration
@ComponentScan

com.example.componentscan.springbootappパッケージで同様の構造を作成しましょう。 今回のメインアプリケーションは次のとおりです。

package com.example.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.example.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

(すべてのBeanを出力するのではなく)2番目の例でBeanの存在を確認しているだけの理由は、出力が大きすぎるためです。

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

3. @ComponentScan引数付き

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

3.1. 特定のパッケージの@ComponentScan

それにはいくつかの方法があります。 最初に、基本パッケージを変更できます。

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

これで、出力は次のようになります。

springComponentScanApp
cat
dog
exampleBean

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

  • springComponentScanAppは、AnnotationConfigApplicationContextに引数として渡される構成であるため作成されます

  • exampleBeanは、構成内で構成されたBeanです。

  • catおよびdogは、指定されたcom.example.componentscan.springapp.animalsパッケージに含まれています

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

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

3.2. 除外を含む@ComponentScan

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

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

the annotation supports several flexible options for filtering the scanned classesのように、別のフィルタータイプを選択することもできます。

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

4. デフォルトパッケージ

@Configurationクラスをin the default packageにすることは避けてください(つまり、 パッケージをまったく指定しないことによって)。 この場合、Springはクラスパス内のすべてのjar内のすべてのクラスをスキャンします。 これによりエラーが発生し、アプリケーションが起動しない可能性があります。

5. 結論

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

いつものように、完全なコードはover on GitHubで利用できます。