1. 概要

このチュートリアルでは、 Spring@Componentアノテーションと関連領域を包括的に見ていきます。 いくつかのコアSpring機能と統合するためにそれを使用できるさまざまな方法と、その多くの利点を活用する方法を見ていきます。

2. Spring ApplicationContext

@Component の値を理解する前に、まず SpringApplicationContextについて少し理解する必要があります。

Spring ApplicationContext は、Springが、自動的に管理および配布されると識別したオブジェクトのインスタンスを保持する場所です。 これらは豆と呼ばれます。

Beanの管理と依存性注入の機会は、Springの主な機能の一部です。

制御の反転の原則を使用して、 SpringはアプリケーションからBeanインスタンスを収集し、適切なタイミングでそれらを使用します。のセットアップとインスタンス化を処理することなく、SpringへのBeanの依存関係を表示できます。それらのオブジェクト。

@Autowired などのアノテーションを使用してSpring管理のBeanをアプリケーションに注入する機能は、Springで強力でスケーラブルなコードを作成するための原動力です。

では、Springに管理してほしいBeanについてどのように伝えるのでしょうか。 クラスでステレオタイプアノテーションを使用して、Springの自動bean検出を利用する必要があります。

3. @Component

@Component は、SpringがカスタムBeanを自動的に検出できるようにするアノテーションです。

つまり、明示的なコードを記述しなくても、Springは次のことを実行します。

  • アプリケーションをスキャンして、@Componentで注釈が付けられたクラスを探します
  • それらをインスタンス化し、指定された依存関係をそれらに挿入します
  • 必要な場所に注入します

ただし、ほとんどの開発者は、この機能を提供するために、より特殊なステレオタイプ注釈を使用することを好みます。

3.1. 春のステレオタイプ注釈

Springは、 @Controller @Service 、および@Repositoryといういくつかの特殊なステレオタイプアノテーションを提供しています。 これらはすべて、@Componentと同じ機能を提供します。

それぞれのメタアノテーションとして@Componentを使用して構成されたアノテーションであるため、すべて同じように動作します。Spring以外での特殊な用途と意味を持つ@Componentエイリアスのようなものです。自動検出または依存性注入。

本当に必要な場合は、理論的には、Beanの自動検出のニーズにのみ@Componentを使用することを選択できます。 反対に、@Componentを使用する独自の特殊な注釈作成することもできます。

ただし、Springには、自動化の利点をさらに提供するためにSpringの特殊な注釈を特に探す他の領域があります。 したがって、ほとんどの場合、確立された専門分野を使用することに固執する必要があります。

Spring Bootプロジェクトにこれらの各ケースの例があると仮定しましょう。

@Controller
public class ControllerExample {
}

@Service
public class ServiceExample {
}

@Repository
public class RepositoryExample {
}

@Component
public class ComponentExample {
}

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Component
public @interface CustomComponent {
}

@CustomComponent
public class CustomComponentExample {
}

それぞれがSpringによって自動検出され、ApplicationContextに追加されることを証明するテストを作成できます。

@SpringBootTest
@ExtendWith(SpringExtension.class)
public class ComponentUnitTest {

    @Autowired
    private ApplicationContext applicationContext;

    @Test
    public void givenInScopeComponents_whenSearchingInApplicationContext_thenFindThem() {
        assertNotNull(applicationContext.getBean(ControllerExample.class));
        assertNotNull(applicationContext.getBean(ServiceExample.class));
        assertNotNull(applicationContext.getBean(RepositoryExample.class));
        assertNotNull(applicationContext.getBean(ComponentExample.class));
        assertNotNull(applicationContext.getBean(CustomComponentExample.class));
    }
}

3.2. @ComponentScan

@Component に完全に依存する前に、それが単なる注釈であることを理解する必要があります。 アノテーションは、ドメインオブジェクトなどの他のオブジェクトからBeanを区別する目的で使用されます。

ただし、 Springは@ComponentScanアノテーションを使用して、実際にそれらすべてをApplicationContextに収集します。

Spring Bootアプリケーションを作成している場合、 @ SpringBootApplication@ComponentScanを含む合成アノテーションであることを知っておくと役に立ちます。 @SpringBootApplication クラスがプロジェクトのルートにある限り、デフォルトで定義されているすべての@Componentをスキャンします。

ただし、 @SpringBootApplication クラスをプロジェクトのルートにできない場合、または外部ソースをスキャンする場合は、 @ComponentScan を明示的に構成して、指定したパッケージを検索できます。 、クラスパスに存在する限り。

範囲外の@Componentbeanを定義しましょう。

package com.baeldung.component.scannedscope;

@Component
public class ScannedScopeExample {
}

次に、@ComponentScanアノテーションへの明示的な指示を介してそれを含めることができます。

package com.baeldung.component.inscope;

@SpringBootApplication
@ComponentScan({"com.baeldung.component.inscope", "com.baeldung.component.scannedscope"})
public class ComponentApplication {
    //public static void main(String[] args) {...}
}

最後に、それが存在することをテストできます。

@Test
public void givenScannedScopeComponent_whenSearchingInApplicationContext_thenFindIt() {
    assertNotNull(applicationContext.getBean(ScannedScopeExample.class));
}

実際には、これは、プロジェクトに含まれている外部の依存関係をスキャンする場合に発生する可能性が高くなります。

3.3. @Component制限

@Component を使用できないときに、特定のオブジェクトをSpringで管理されるbeanにするシナリオがいくつかあります。

プロジェクト外のパッケージで、@Componentで注釈が付けられたオブジェクトを定義しましょう。

package com.baeldung.component.outsidescope;

@Component
public class OutsideScopeExample {
}

ApplicationContextに外部コンポーネントが含まれていないことを証明するテストを次に示します。

@Test
public void givenOutsideScopeComponent_whenSearchingInApplicationContext_thenFail() {
    assertThrows(NoSuchBeanDefinitionException.class, () -> applicationContext.getBean(OutsideScopeExample.class));
}

また、ソースコードはサードパーティのソースからのものであり、 @Component アノテーションを追加できないため、ソースコードにアクセスできない可能性があります。 または、実行している環境に応じて、あるbean実装を別の実装よりも条件付きで使用したい場合があります。 ほとんどの場合、自動検出で十分ですが、そうでない場合は、@Beanを使用できます。

4. @Component@Bean

@ Bean は、Springが実行時にbeanを収集するために使用するアノテーションでもありますが、クラスレベルでは使用されません。 代わりに、メソッドに@ Beanのアノテーションを付けて、Springがメソッドの結果をSpringbean。として保存できるようにします。

まず、注釈のないPOJOを作成します。

public class BeanExample {
}

@Configuration で注釈が付けられたクラス内で、Bean生成メソッドを作成できます。

@Bean
public BeanExample beanExample() {
    return new BeanExample();
}

BeanExample は、ローカルクラスを表す場合もあれば、外部クラスを表す場合もあります。 単にそのインスタンスを返す必要があるので、それは問題ではありません。

次に、SpringがBeanを取得したことを確認するテストを作成できます。

@Test
public void givenBeanComponent_whenSearchingInApplicationContext_thenFindIt() {
    assertNotNull(applicationContext.getBean(BeanExample.class));
}

@Component@Beanには違いがあるため、注意すべき重要な意味がいくつかあります。

  • @Component はクラスレベルのアノテーションですが、 @ Bean はメソッドレベルであるため、@Componentはクラスのソースコードの場合のオプションにすぎません。編集可能です。 @ Bean はいつでも使用できますが、より冗長です。
  • @Component はSpringの自動検出と互換性がありますが、 @Beanは手動でクラスをインスタンス化する必要があります。
  • @Bean を使用すると、Beanのインスタンス化がクラス定義から切り離されます。 これが、サードパーティのクラスでさえSpringBeanにするために使用できる理由です。 また、Beanで使用できるいくつかのインスタンスオプションのどれを使用するかを決定するロジックを導入できることも意味します。

5. 結論

Spring @Componentアノテーションとその他の関連トピックについて説明しました。 最初に、@Componentの特殊なバージョンであるさまざまなSpringステレオタイプアノテーションについて説明しました。

次に、 @Component は、 @ComponentScan で検出されない限り、何も実行しないことを学びました。

最後に、ソースコードがないクラスでは @Component を使用できないため、代わりに @Beanアノテーションを使用する方法を学びました。

これらすべてのコード例とその他の例は、GitHubにあります。