<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>
動作を理解するために必要なすべてであることを願っています
。