<context:annotation-config> アプリケーションコンテキストにすでに登録されているBeanの注釈をアクティブ化するために使用されます(XMLで定義されたか、パッケージスキャンで定義されたかに関係なく)。
<context:component-scan>また、何を行うことができ<context:annotation-config>ませんが、<context:component-scan>また、アプリケーションのコンテキスト内で豆を見つけて登録するパッケージをスキャンします。
いくつかの例を使用して、相違点/類似点を示します。
タイプの3つの豆の基本的なセットアップを開始することができますA、BそしてC、とBとCに注入されます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とcccプロパティを次のように自動ワイヤリングしますA。
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
はい、これは間違っています!どうした?プロパティが自動配線されないのはなぜですか?
まあ、注釈は素晴らしい機能ですが、それだけでは何もしません。注釈を付けるだけです。注釈を見つけてそれを処理するための処理ツールが必要です。
<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は作成されず、自動ワイヤリングも行われません。何もない!
これは、最初の段落で述べたように<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
うーん...何かが欠けています。どうして?
あなたはクラスでcloselly見ると、クラスがAパッケージを持っているcom.yyyが、私はで指定した<context:component-scan>パッケージを使用するためにcom.xxx、これは完全に私逃したので、Aクラスを唯一のピックアップBとCその上にあるcom.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、BかつCおよびXMLに次を追加し、我々はコンテキストをロードした後に何を得るのだろうか?
<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
AスキャンによってクラスのBean が取得されない場合でも、XMLに手動で登録されていたとして<context:component-scan>も、アプリケーションコンテキストに登録されているすべてのBeanに処理ツールが適用されAます。
しかし、我々は、以下のXMLを持っている場合、我々は両方を指定したので、豆を重複してしまいます<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
わかりました。それで終わりです。
この情報と、@ Tomasz Nurkiewiczと@Sean Patrick Floydからの回答が、方法<context:annotation-config>と<context:component-scan>動作を理解するために必要なすべてであることを願っています
。