Spring:@Componentと@Bean


459

@Componentクラスパススキャンを使用してXML Bean定義を取り除くために、Spring 2.5でアノテーションが導入されたことを理解しています。

@BeanはSpring 3.0で導入され@Configuration、xmlファイルを完全に削除し、代わりにjava configを使用するために使用できます。

@Componentアノテーションを導入する代わりにアノテーションを再利用することは可能@Beanでしたか?私の理解では、最終的な目標はどちらの場合もBeanを作成することです。


4
構成クラス以外に@Beanを使用できる場所はありますか?
Willa


@Willaはい、あります。それはと呼ばれていLite modeます。そして、それはお勧めできません。ここを参照してください:docs.spring.io/spring/docs/current/spring-framework-reference/...
smwikipedia

9
まとめると、のメソッドがSpring @beanBeanのカスタマイズ可能なインスタンスを返す一方で@component、必要に応じてSpring IoCエンジンによって後でインスタンス化される可能性があるクラスを定義していると要約します。
セバス2017年

回答:


433

@Componentそして@Bean2つの全く異なることを行う、と混同してはなりません。

@Component(および@Serviceおよび@Repository)は、クラスパススキャンを使用してBeanを自動検出および自動設定するために使用されます。注釈付きクラスとBeanの間には、暗黙的な1対1のマッピングがあります(つまり、クラスごとに1つのBean)。このアプローチでは、純粋に宣言型であるため、配線の制御はかなり制限されます。

@Bean上記のようにSpringに自動的に実行させるのではなく、単一のBean を明示的に宣言するために使用されます。Beanの宣言をクラス定義から切り離し、選択したとおりにBeanを作成および構成できます。

あなたの質問に答えるには...

@Componentアノテーションを導入する代わりにアノテーションを再利用することは可能@Beanでしたか?

確かに、おそらく; しかし、彼らはそうしないことを選びました。春はすでに水を濁らせずに十分に混乱しています。


3
だから私は@Component自動配線が必要なときにのみ使用できますか?@Bean影響はないようです@Autowired
Jaskey 2015年

3
サービスベースのクラスには '@component'を使用し、ファクトリーとしてよりカスタムメイドのオブジェクトとして '@Bean'を使用します(例:jdbcデータソース
Junchen Liu

2
あなたが使用することができます@Jaskey @Autowired@BeanあなたとあなたのBeanクラスを注釈を付けている場合@Configuration
starcorn

6
申し訳ありませんが、あなたの説明の言葉が理解できません。これを明確に理解しているので、明確な説明を書くか、適切なドキュメントを示してください。
Alex Worden

13
私は(他の人の答えを読むことから)概念を理解したので、あなたの説明は理にかなっています。これは、あなたの説明がまだ概念を理解していない誰にとっても役に立たないことをいっそうわかります。
Alex Worden

397

@ コンポーネントコンポーネントのスキャンと自動配線に適しています。

いつ@Beanを使用する必要がありますか?

自動構成はオプションではない場合があります。いつ?サードパーティのライブラリからコンポーネントをワイヤリングしたいとしましょう(ソースコードがないため、@ Componentでクラスに注釈を付けることはできません)。したがって、自動構成は不可能です。

@Bean注釈は、オブジェクト戻りばねがアプリケーションコンテキストにBeanとして登録するべきです。メソッド本体には、インスタンスを作成するロジックがあります。


5
これは最も理にかなっていると思います。私が正しく理解していれば、クラスメソッド(クラスオブジェクトのインスタンスを生成する)に行く@Component間、クラス自体に@Bean行きます。
jocull 2018

182

動的な状態に応じて特定の実装が必要だと考えてみましょう。 @Beanその場合に最適です。

@Bean
@Scope("prototype")
public SomeService someService() {
    switch (state) {
    case 1:
        return new Impl1();
    case 2:
        return new Impl2();
    case 3:
        return new Impl3();
    default:
        return new Impl();
    }
}

ただし、でそれを行う方法はありません@Component


3
その例のクラスをどのように呼びますか?
PowerFlower 2017年

1
@PowerFlowerこのメソッドは、注釈付きの構成クラス内にある必要があります@Configuration
Juh_

98
  1. @Component クラスパススキャンを使用してBeanを自動的に検出して構成しますが、@ BeanはSpringに自動的に実行させるのではなく、単一のBeanを明示的に宣言します。
  2. @Component Beanの宣言をクラス定義から切り離しませんが、@ BeanはBeanの宣言をクラス定義から切り離します。
  3. @Componentはクラスレベルのアノテーションですが、@ Beanはメソッドレベルのアノテーションであり、メソッドの名前はBean名として機能します。
  4. @Component は@Configurationアノテーションとともに使用する必要はありません。@ Configurationアノテーションが付けられたクラス内@Beanアノテーションを使用する必要があるためです
  5. 私たちは豆を作成することはできません我々は一方でクラスが外側スプリングコンテナである場合、@Componentを使用して、クラスのを豆作成できるクラスが存在する場合であっても@Beanを使用して、クラスのを春のコンテナの外
  6. @Componentには@ Controller、@ Repository、@ Serviceなどの異なる特殊化がありますが、@ Beanには特殊化はありません

3
4.実際には、@ Beanは非構成クラスで宣言できます。ライトモードとして知られています
voipp '29

1
ポイント5について。春のコンテナの中に豆を入れたと思います。したがって、すべてのクラスは春のコンテナの外にあります。ポイント5は報われるべきだと思います
eugen

97

どちらのアプローチも、Springコンテナにターゲットタイプを登録することを目的としています。

違いはある@Beanにも適用可能である方法のに対し、@Componentに適用可能であるタイプ

したがって、@Beanアノテーションを使用する場合は、メソッドの本体でインスタンス作成ロジックを制御します(上記の例を参照)。@Component注釈あなたがすることはできません。


タイプとは何ですか?
Jac Frall

20

私は多くの答えを目にしますが、ほぼすべての箇所で言及されている@Componentはコンポーネントがスキャンされ、@ BeanがそのBeanを別の方法で使用することを正確に宣言している自動配線用です。その違いをお見せしましょう。

  • @豆

まず、メソッドレベルのアノテーションです。次に、一般にJavaコードでBeanを構成するために使用し(xml構成を使用していない場合)、ApplicationContextのgetBeanメソッドを使用してクラスから呼び出します。お気に入り

 @Configuration
class MyConfiguration{
    @Bean
    public User getUser(){
        return new User();
    }
}

class User{
}



//Getting Bean 
User user = applicationContext.getBean("getUser");
  • @成分

これは、特殊なBeanではなく、Beanに注釈を付ける一般的な方法です。クラスレベルの注釈であり、javaまたはxml構成を介してすべての構成を回避するために使用されます。

私たちはこのようなものを手に入れます。

@Component
class User {
}

//to get Bean
@Autowired
User user;

それでおしまい 。これは、そのBeanをインスタンス化して使用するためのすべての構成手順を回避するために導入されたばかりです。


5
@Beanアプローチを使用する場合、ApplicationContextからUserオブジェクトを取得する必要はないと思います。の@Autowire場合と同様に、引き続きを使用してBeanを取得できます@Component@BeanBeanをSpring Containerに追加するだけ@Componentです。違いは以下の通りです。1.を使用して@Bean、Spring Containerにサードパーティクラスを追加できます。2.を使用すると@Bean、実行時にインターフェースの望ましい実装を取得できます(ファクトリーデザインパターンを使用)
Andy

20

を使用@Beanして、既存のサードパーティクラスをSpringフレームワークアプリケーションコンテキストで使用できるようにすることができます。

@Bean
public ViewResolver viewResolver() {

    InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();

    viewResolver.setPrefix("/WEB-INF/view/");
    viewResolver.setSuffix(".jsp");

    return viewResolver;
}

@Beanアノテーションを使用することで、サードパーティのクラス(@ComponentSpring Beanがなくても、Springを使用しない場合もあります)をSpring Beanとしてラップできます。そして、を使用してラップする@Beanと、シングルトンオブジェクトとして、Springフレームワークアプリケーションコンテキストで使用できるようになります。依存性注入とを使用して、このBeanをアプリで簡単に共有/再利用できるようになりました@Autowired

したがって、@Beanアノテーションはサードパーティのクラスのラッパー/アダプターであると考えてください。サードパーティのクラスをSpringフレームワークアプリケーションコンテキストで利用できるようにしたい。

@Bean上記のコードで使用することにより、メソッド内でnewキーワードを使用してオブジェクトを明示的に作成しているため、単一のBeanを明示的に宣言しています。また、指定されたクラスのセッターメソッドを手動で呼び出しています。プレフィックスフィールドの値を変更できます。したがって、この手作業は明示的作成と呼ばれます。@Component同じクラスにを使用すると、Springコンテナに登録されたBeanのプレフィックスフィールドのデフォルト値が使用されます。

一方、クラスにで注釈を付ける@Component場合、newキーワードを手動で使用する必要はありません。これはSpringによって自動的に処理されます。


1
この答えは、そのBeanがうまくとして使用されている方法の例で更新された場合はいいだろう
softarn

ソースコードで変更が許可されていない場合、@ Beanをサードパーティのクラスでどのようにラップしますか?
ベリタス

16

@Componentタグを使用する場合、これはバニラBean宣言メソッド(注釈付き)を備えたPOJO(Plain Old Java Object)を持つのと同じ@Beanです。たとえば、次の方法1と2は同じ結果になります。

方法1

@Component
public class SomeClass {

    private int number;

    public SomeClass(Integer theNumber){
        this.number = theNumber.intValue();
    }

    public int getNumber(){
        return this.number;
    }
}

'theNumber'のBeanを使用:

@Bean
Integer theNumber(){
    return new Integer(3456);
}

方法2

//Note: no @Component tag
public class SomeClass {

    private int number;

    public SomeClass(Integer theNumber){
        this.number = theNumber.intValue();
    }

    public int getNumber(){
        return this.number;
    }
}

両方の豆で:

@Bean
Integer theNumber(){
    return new Integer(3456);
}

@Bean
SomeClass someClass(Integer theNumber){
    return new SomeClass(theNumber);
}

方法2では、Bean宣言を一緒にしておくことができます。これは少し柔軟性があります。以下のような、バニラではない別のSomeClass Beanを追加することもできます。

@Bean
SomeClass strawberryClass(){
    return new SomeClass(new Integer(1));
}

10

Beanを生成するには2つの方法があります。1つは、アノテーション付きのクラスを作成すること@Componentです。もう1つは、メソッドを作成してで注釈を付けること@Beanです。を含むメソッドが含まれているクラスの@Bean場合、アノテーションを付ける必要があります。Spring @Configuration プロジェクトを実行すると、@ComponentScanアノテーションを含むクラスは@Component、その上にあるすべてのクラスをスキャンし、このクラスのインスタンスをIocコンテナに復元します。もう1つのことは@ComponentScan、メソッドをその@Bean上で実行し、戻りオブジェクトをBeanとしてIocコンテナーに復元することです。したがって、現在の状態に応じて作成するBeanの種類を決定する必要がある場合は、@Bean。ロジックを記述して、必要なオブジェクトを返すことができます。もう1つ注目すべきことは、メソッドの@Bean名前がBeanのデフォルト名であることです。


6
  • @componentとその特殊化(@ Controller、@ service、@ repository)により、クラスパススキャンを使用した自動検出が可能になります。@ Controller、@ serviceなどのコンポーネントクラスが表示される場合、@ repositoryはコンポーネントスキャンを使用してSpring Frameworkによって自動的にスキャンされます。
  • 一方、@ Beanは、構成クラスで単一のBeanを明示的に宣言するためにのみ使用できます。
  • @Beanは、Springに自動的に実行させるのではなく、単一のBeanを明示的に宣言するために使用されていました。そのクラス定義からのBeanの隔壁宣言を行います。
  • つまり、@ Controller、@ service、@ repositoryは自動検出用であり、@ Beanはクラスから個別のBeanを作成します
    -@コントローラー
    パブリッククラスLoginController 
    {-コード-}

    -@構成
    パブリッククラスAppConfig {
    @豆
    public SessionFactory sessionFactory() 
    {-コード-}

3

@Beanは、コンパイル時にSpringとビジネスルールの結合を回避するために作成されました。これは、PlayFrameworkやJEEなどの他のフレームワークでビジネスルールを再利用できることを意味します。

さらに、Beanの作成方法を完全に制御できます。デフォルトのSpringインスタンス化では不十分です。

私はそれについて話す記事を書きました。

https://coderstower.com/2019/04/23/factory-methods-decoupling-ioc-container-abstraction/



1

1. @Configurationと
同様に@Component @Component関数について

どちらも、アノテーション付きクラスには、1つ以上のBeanを登録する必要があることを示していSpring-IOC-Containerます。

@Componentによって注釈が付けられたクラスを、これと呼びますComponent of Spring。これは、いくつかのBeanを含む概念です。

Component classのBeanを登録するには、Springで自動スキャンする必要がありますcomponent class

2. @Beanについて@Bean
component-class(上記のように)のメソッドに注釈を付けるために使用されます。これは、アノテーション付きメソッドによって取得されたインスタンスをに登録する必要があることを示していますSpring-IOC-Container

3.結論
2つの違いは比較的明白different circumstancesです。これらはで使用されています。一般的な使用法は次のとおりです。

    // @Configuration is implemented by @Component
    @Configuration
    public ComponentClass {

      @Bean
      public FirstBean FirstBeanMethod() {
        return new FirstBean();
      }

      @Bean
      public SecondBean SecondBeanMethod() {
        return new SecondBean();
      }
    }

0

上記の回答からの追加ポイント

複数のアプリで共有され、いくつかのサービスを含むモジュールがあるとします。各アプリにすべてが必要なわけではありません。

これらのサービスクラスで@Componentを使用し、アプリケーションでコンポーネントをスキャンする場合、

必要以上の豆を検出してしまうかもしれません

この場合、コンポーネントスキャンのフィルタリングを調整するか、未使用のBeanでも実行できる構成を提供する必要がありました。そうしないと、アプリケーションコンテキストが起動しません。

この場合、@ Beanアノテーションを使用して、それらのBeanのみをインスタンス化することをお勧めします。

各アプリで個別に必要な

したがって、基本的に、コンテキストにサードパーティのクラスを追加するには@Beanを使用します。また、@ Componentが単一のアプリケーション内にある場合。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.