715

私はSpring 3を学んでいます.andの背後にある機能を理解していないよう<context:annotation-config>です<context:component-scan>.

私が読んだことから、彼らは異なる注釈@Required@Autowiredetc vs @Component@Repository@Serviceなど)を処理しているように見えますが、私が読んだことからも、同じBeanポストプロセッサクラスを登録しています。

私をさらに混乱させるために、 にannotation-config 属性があります<context:component-scan>

誰かがこれらのタグに光を当てることができますか? 何が似ていて、何が違うのか、一方が他方に取って代わられているのか、それらは互いに補完し合っているのか、どちらか一方が必要なのか、両方が必要なのか?

4

15 に答える 15

1466

<context:annotation-config>アプリケーションコンテキストにすでに登録されているBeanのアノテーションをアクティブ化するために使用されます(XMLで定義されているか、パッケージスキャンで定義されているかは関係ありません)。

<context:component-scan>また、パッケージをスキャンして、アプリケーションコンテキスト内でBeanを検索および登録することも<context:annotation-config>できます。<context:component-scan>

いくつかの例を使用して、相違点/類似点を示します。

Aタイプが、、の3つのBeanの基本的なセットアップから始めましょう。BそしてCBC注入されAます。

package com.xxx;
public class B {
  public B() {
    System.out.println("creating bean B: " + this);
  }
}

package com.xxx;
public class C {
  public C() {
    System.out.println("creating bean C: " + this);
  }
}

package com.yyy;
import com.xxx.B;
import com.xxx.C;
public class A { 
  private B bbb;
  private C ccc;
  public A() {
    System.out.println("creating bean A: " + this);
  }
  public void setBbb(B bbb) {
    System.out.println("setting A.bbb with " + bbb);
    this.bbb = bbb;
  }
  public void setCcc(C ccc) {
    System.out.println("setting A.ccc with " + ccc);
    this.ccc = ccc; 
  }
}

次のXML構成の場合:

<bean id="bBean" class="com.xxx.B" />
<bean id="cBean" class="com.xxx.C" />
<bean id="aBean" class="com.yyy.A">
  <property name="bbb" ref="bBean" />
  <property name="ccc" ref="cBean" />
</bean>

コンテキストをロードすると、次の出力が生成されます。

creating bean B: com.xxx.B@c2ff5
creating bean C: com.xxx.C@1e8a1f6
creating bean A: com.yyy.A@1e152c5
setting A.bbb with com.xxx.B@c2ff5
setting A.ccc with com.xxx.C@1e8a1f6

OK、これは期待される出力です。しかし、これは「古いスタイル」の春です。これで注釈ができたので、それらを使用してXMLを単純化してみましょう。

まず、次のようにBeanのプロパティbbbとプロパティを自動配線します。cccA

package com.yyy;
import org.springframework.beans.factory.annotation.Autowired;
import com.xxx.B;
import com.xxx.C;
public class A { 
  private B bbb;
  private C ccc;
  public A() {
    System.out.println("creating bean A: " + this);
  }
  @Autowired
  public void setBbb(B bbb) {
    System.out.println("setting A.bbb with " + bbb);
    this.bbb = bbb;
  }
  @Autowired
  public void setCcc(C ccc) {
    System.out.println("setting A.ccc with " + ccc);
    this.ccc = ccc;
  }
}

これにより、XMLから次の行を削除できます。

<property name="bbb" ref="bBean" />
<property name="ccc" ref="cBean" />

私のXMLは次のように簡略化されています。

<bean id="bBean" class="com.xxx.B" />
<bean id="cBean" class="com.xxx.C" />
<bean id="aBean" class="com.yyy.A" />

コンテキストをロードすると、次の出力が得られます。

creating bean B: com.xxx.B@5e5a50
creating bean C: com.xxx.C@54a328
creating bean A: com.yyy.A@a3d4cf

OK、これは間違っています!どうしたの?プロパティが自動配線されないのはなぜですか?

まあ、注釈は素晴らしい機能ですが、それ自体では何もしません。彼らはただものに注釈を付けます。注釈を見つけてそれを使って何かをするための処理ツールが必要です。

<context:annotation-config>救助へ。これにより、それ自体が定義されているのと同じアプリケーションコンテキストで定義されているBeanで検出されたアノテーションのアクションがアクティブになります。

XMLを次のように変更した場合:

<context:annotation-config />
<bean id="bBean" class="com.xxx.B" />
<bean id="cBean" class="com.xxx.C" />
<bean id="aBean" class="com.yyy.A" />

アプリケーションコンテキストをロードすると、適切な結果が得られます。

creating bean B: com.xxx.B@15663a2
creating bean C: com.xxx.C@cd5f8b
creating bean A: com.yyy.A@157aa53
setting A.bbb with com.xxx.B@15663a2
setting A.ccc with com.xxx.C@cd5f8b

OK、これは素晴らしいですが、XMLから2つの行を削除し、1つ追加しました。それはそれほど大きな違いではありません。注釈の考え方は、XMLを削除することになっているということです。

それでは、XML定義を削除して、それらすべてを注釈に置き換えましょう。

package com.xxx;
import org.springframework.stereotype.Component;
@Component
public class B {
  public B() {
    System.out.println("creating bean B: " + this);
  }
}

package com.xxx;
import org.springframework.stereotype.Component;
@Component
public class C {
  public C() {
    System.out.println("creating bean C: " + this);
  }
}

package com.yyy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.xxx.B;
import com.xxx.C;
@Component
public class A { 
  private B bbb;
  private C ccc;
  public A() {
    System.out.println("creating bean A: " + this);
  }
  @Autowired
  public void setBbb(B bbb) {
    System.out.println("setting A.bbb with " + bbb);
    this.bbb = bbb;
  }
  @Autowired
  public void setCcc(C ccc) {
    System.out.println("setting A.ccc with " + ccc);
    this.ccc = ccc;
  }
}

XMLにある間、私たちはこれだけを保持します:

<context:annotation-config />

コンテキストをロードすると、結果は...何もありません。Beanは作成されず、Beanは自動配線されません。何もない!

これは、最初の段落で述べたように<context:annotation-config />、アプリケーションコンテキスト内で登録されたBeanでのみ機能するためです。3つのBeanのXML構成を削除したため、Beanは作成されず<context:annotation-config />、作業する「ターゲット」もありません。

しかし、それは<context:component-scan>、パッケージをスキャンして「ターゲット」が機能するかどうかについては問題になりません。XML構成の内容を次のエントリに変更してみましょう。

<context:component-scan base-package="com.xxx" />

コンテキストをロードすると、次の出力が得られます。

creating bean B: com.xxx.B@1be0f0a
creating bean C: com.xxx.C@80d1ff

うーん...何かが足りない。なんで?

クラスをよく見ると、クラスにAはパッケージがありますが、使用するパッケージをcom.yyy指定したので、これは私のクラスを完全に見逃し、パッケージに含まれているものだけを取得しました。<context:component-scan>com.xxxABCcom.xxx

これを修正するために、この他のパッケージも追加します。

<context:component-scan base-package="com.xxx,com.yyy" />

そして今、私たちは期待される結果を得る:

creating bean B: com.xxx.B@cd5f8b
creating bean C: com.xxx.C@15ac3c9
creating bean A: com.yyy.A@ec4a87
setting A.bbb with com.xxx.B@cd5f8b
setting A.ccc with com.xxx.C@15ac3c9

以上です!これで、XML定義はなくなり、注釈が付けられました。

最後の例として、注釈付きクラスを保持Aし、XMLに以下を追加するBC、コンテキストをロードした後に何が得られますか?

<context:component-scan base-package="com.xxx" />
<bean id="aBean" class="com.yyy.A" />

それでも正しい結果が得られます。

creating bean B: com.xxx.B@157aa53
creating bean C: com.xxx.C@ec4a87
creating bean A: com.yyy.A@1d64c37
setting A.bbb with com.xxx.B@157aa53
setting A.ccc with com.xxx.C@ec4a87

クラスのBeanがAスキャンによって取得されない場合でも、処理ツールは、XMLに手動で登録されている<context:component-scan>場合でも、アプリケーションコンテキストに登録されているすべてのBeanに適用されます。A

しかし、次のXMLがある場合、との両方を指定したため、重複したBeanが取得されます<context:annotation-config /><context:component-scan>

<context:annotation-config />
<context:component-scan base-package="com.xxx" />
<bean id="aBean" class="com.yyy.A" />

いいえ、重複はありません。再び期待される結果が得られます。

creating bean B: com.xxx.B@157aa53
creating bean C: com.xxx.C@ec4a87
creating bean A: com.yyy.A@1d64c37
setting A.bbb with com.xxx.B@157aa53
setting A.ccc with com.xxx.C@ec4a87

これは、両方のタグが同じ処理ツールを登録しているためです(指定さ<context:annotation-config />れている場合は省略でき<context:component-scan>ます)が、Springはそれらの実行を1回だけ処理します。

自分で処理ツールを複数回登録した場合でも、Springはそれらが魔法を1回だけ実行することを確認します。このXML:

<context:annotation-config />
<context:component-scan base-package="com.xxx" />
<bean id="aBean" class="com.yyy.A" />
<bean id="bla" class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
<bean id="bla1" class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
<bean id="bla2" class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
<bean id="bla3" class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />

それでも次の結果が生成されます。

creating bean B: com.xxx.B@157aa53
creating bean C: com.xxx.C@ec4a87
creating bean A: com.yyy.A@25d2b2
setting A.bbb with com.xxx.B@157aa53
setting A.ccc with com.xxx.C@ec4a87

OK、それで終わりです。

この情報と@TomaszNurkiewiczおよび@SeanPatrickFloydからの回答が、どのよう <context:annotation-config>に機能するかを理解するために必要なすべてであることを願っています<context:component-scan>

于 2011-09-17T17:16:46.937 に答える
170

どの注釈がどの宣言によって取得されるかについて、この素晴らしい要約を見つけました。<context:component-scan/>これを調べると、 が によって認識されるアノテーションのスーパーセットを認識することがわかります<context:annotation-config/>。つまり、次のとおりです。

  • @Component@Service@Repository@Controller@Endpoint
  • @Configuration@Bean@Lazy@Scope@Order@Primary@Profile@DependsOn_ @Import_@ImportResource

ご覧のとおり、CLASSPATH コンポーネント スキャンと Java @Configuration 機能によって<context:component-scan/>論理的に拡張されています。 <context:annotation-config/>

于 2011-09-14T10:39:59.553 に答える
39

<context:annotation-config>XML で定義されているか、コンポーネント スキャンによって定義されているかに関係なく、Bean 内のさまざまな注釈をアクティブにします。

<context:component-scan>XMLを使用せずにBeanを定義するためのものです

詳細については、次を参照してください。

于 2011-09-14T10:41:53.577 に答える
34

<context:annotation-config>: spring config xml に既に登録されている Bean の注釈をスキャンしてアクティブ化します。

<context:component-scan>ビーン登録+<context:annotation-config>


@Autowired と @Requiredターゲット プロパティ レベルであるため、Bean はこれらのアノテーションを使用する前に Spring IOC に登録する必要があります。これらのアノテーションを有効にするには、それぞれの Bean を登録するか、<context:annotation-config />. つまり<context:annotation-config />、登録された Bean のみで動作します。

@RequiredRequiredAnnotationBeanPostProcessor 処理ツールを有効にします
@AutowiredAutowiredAnnotationBeanPostProcessorは処理ツールを有効に します

注:注釈自体は何もする必要はありません。処理ツールが必要です。これは、その下にあるクラスであり、コア プロセスを担当します。


@Repository、@Service、@Controller は @Componentであり、クラス レベルを対象としています。

<context:component-scan>パッケージをスキャンし、Bean を見つけて登録します<context:annotation-config />

XML を注釈に移行する

于 2016-01-02T02:22:35.857 に答える
18
<context:annotation-config>

@Autowiredおよび@Qualiferアノテーションのみを解決します。それだけです。依存性注入についてです。同じ仕事をする他のアノテーションがあります。どうやってだと思います@Injectが、アノテーションを介してDIを解決しようとしています。

<context:annotation-config>要素を宣言した場合でも、クラスを Bean として宣言する必要があることに注意してください。3 つの使用可能なオプションがあることを覚えておいてください。

  • XML:<bean>
  • @アノテーション: @Component、@Service、@Repository、@Controller
  • JavaConfig: @Configuration、@Bean

今と

<context:component-scan>

次の 2 つのことを行います。

  • @Component、@Service、@Repository、@Controller、および @Configuration でアノテーションが付けられたすべてのクラスをスキャンし、Bean を作成します。
  • それはどのように同じ仕事を<context:annotation-config>します。

したがって、 を宣言する場合<context:component-scan>は、もう宣言する必要はありませ<context:annotation-config>ん。

それで全部です

一般的なシナリオは、たとえば、XML を介して Bean のみを宣言し、注釈を介して DI を解決することでした。

<bean id="serviceBeanA" class="com.something.CarServiceImpl" />
<bean id="serviceBeanB" class="com.something.PersonServiceImpl" />
<bean id="repositoryBeanA" class="com.something.CarRepository" />
<bean id="repositoryBeanB" class="com.something.PersonRepository" />

<constructor-arg>Bean のみを宣言し、 andについては何も宣言していません<property>。DI は @Autowired を介して独自のクラスで構成されています。これは、サービスがリポジトリ コンポーネントに @Autowired を使用し、リポジトリが JdbcTemplate、DataSource などに @Autowired を使用することを意味します。

于 2014-06-06T13:28:57.823 に答える
15

この<context:annotation-config>タグは、@Autowired アノテーションを含むクラスの依存関係要件を自動的に解決するためにコードベースをスキャンするように Spring に指示します。

Spring 2.5 では、@Resource、@PostConstruct、@PreDestroy などの JSR-250 アノテーションのサポートも追加されています。これらのアノテーションを使用するには、Spring コンテナー内に特定の BeanPostProcessor を登録する必要もあります。<context:annotation-config>いつものように、これらは個々の Bean 定義として登録できますが、Spring 構成にタグを含めることで暗黙的に登録することもできます。

Annotation Based Configurationの Spring ドキュメントから取得


Spring は、「ステレオタイプ化された」クラスを自動的に検出し、対応する BeanDefinitions を ApplicationContext に登録する機能を提供します。

org.springframework.stereotypeの javadoc によると:

ステレオタイプは、アーキテクチャ全体 (実装レベルではなく概念レベル) における型またはメソッドの役割を示す注釈です。例: @Controller @Service @Repository など。これらは、ツールとアスペクトで使用することを目的としています (ポイントカットの理想的なターゲットになります)。

このような「ステレオタイプ」クラスを自動検出するには、<context:component-scan>タグが必要です。

この<context:component-scan>タグは、指定されたパッケージ (およびそのすべてのサブパッケージ) の下で注入可能な Bean のコードをスキャンするように Spring に指示します。

于 2012-08-31T09:08:20.050 に答える
7
<context:component-scan /> implicitly enables <context:annotation-config/>

で試してみて<context:component-scan base-package="..." annotation-config="false"/>ください。構成で@Service、@Repository、@Componentは正常に動作しますが、@Autowired、@Resource、および@Injectは動作しません。

これは、 AutowiredAnnotationBeanPostProcessorが有効にならず、Spring コンテナーが Autowiring アノテーションを処理しないことを意味します。

于 2014-10-03T18:30:04.230 に答える
5
<context:annotation-config/> <!-- is used to activate the annotation for beans -->
<context:component-scan base-package="x.y.MyClass" /> <!-- is for the Spring IOC container to look for the beans in the base package. -->

注意すべきもう 1 つの重要な点は、context:component-scan暗黙的に を呼び出して、context:annotation-configBean のアノテーションをアクティブにすることです。アノテーションを暗黙的に有効にしたくない場合は、 tocontext:component-scanの annotation-config 要素の設定に進むことができます。context:component-scanfalse

要約する:

<context:annotation-config/> <!-- activates the annotations --> 
<context:component-scan base-package="x.y.MyClass" /> <!-- activates the annotations + register the beans by looking inside the base-package -->
于 2015-04-10T16:05:19.560 に答える
1

<context:component-scan base-package="package name" />:

これは、パッケージに Bean クラスがあることをコンテナに伝えるために使用され、それらの Bean クラスをスキャンします。Bean 上のコンテナで Bean クラスをスキャンするには、次のようなステレオ タイプ アノテーションの 1 つを記述する必要があります。

@Component@Service@Repository@Controller

<context:annotation-config />:

XML で明示的に bean タグを書きたくない場合は、Bean に自動配線があるかどうかをコンテナーがどのように認識するか。これは、@Autowiredアノテーションを使用することで可能になります。によって、Bean に自動配線があることをコンテナーに通知する必要がありcontext:annotation-configます。

于 2015-01-29T01:35:15.157 に答える
0

<context:annotation-config>:

@Autowiredこれは、Spring 構成xml ファイルで宣言する代わりに、注釈付きの Bean を Spring Bean として使用し、それらを注釈を介して配線することを Spring に伝えます。

<context:component-scan base-package="com.test...">:

これにより、アノテーション付き Bean の検索を開始する場所が Spring コンテナーに通知されます。ここで、Spring は基本パッケージのすべてのサブパッケージを検索します。

于 2015-12-30T11:16:43.920 に答える
0

<context:component-scan/>カスタム タグは、Java パッケージのスキャンとクラスパスからの Bean 定義の登録という主な役割を除けば、 によって行われるのと同じ Bean 定義のセットを登録します。

何らかの理由でデフォルト Bean 定義のこの登録を回避する必要がある場合、その方法は、次のように component-scan で追加の「annotation-config」属性を指定することです。

<context:component-scan basePackages="" annotation-config="false"/>

参照: http://www.java-allandsundry.com/2012/12/contextcomponent-scan-contextannotation.html

于 2013-06-15T06:56:20.203 に答える
0

詳細については、Spring コンテキスト スキーマ ファイルを参照してください。以下は spring-context-4.3.xsd にあります

<conxtext:annotation-config />
Activates various annotations to be detected in bean classes: Spring's @Required and
@Autowired, as well as JSR 250's @PostConstruct, @PreDestroy and @Resource (if available),
JAX-WS's @WebServiceRef (if available), EJB 3's @EJB (if available), and JPA's
@PersistenceContext and @PersistenceUnit (if available). Alternatively, you may
choose to activate the individual BeanPostProcessors for those annotations.

Note: This tag does not activate processing of Spring's @Transactional or EJB 3's
@TransactionAttribute annotation. Consider the use of the <tx:annotation-driven>
tag for that purpose.
<context:component-scan>
Scans the classpath for annotated components that will be auto-registered as
Spring beans. By default, the Spring-provided @Component, @Repository, @Service, @Controller, @RestController, @ControllerAdvice, and @Configuration stereotypes    will be detected.

Note: This tag implies the effects of the 'annotation-config' tag, activating @Required,
@Autowired, @PostConstruct, @PreDestroy, @Resource, @PersistenceContext and @PersistenceUnit
annotations in the component classes, which is usually desired for autodetected components
(without external configuration). Turn off the 'annotation-config' attribute to deactivate
this default behavior, for example in order to use custom BeanPostProcessor definitions
for handling those annotations.

Note: You may use placeholders in package paths, but only resolved against system
properties (analogous to resource paths). A component scan results in new bean definitions
being registered; Spring's PropertySourcesPlaceholderConfigurer will apply to those bean
definitions just like to regular bean definitions, but it won't apply to the component
scan settings themselves.
于 2019-02-01T08:22:49.713 に答える