<context:annotation-config>
アプリケーションコンテキストにすでに登録されているBeanのアノテーションをアクティブ化するために使用されます(XMLで定義されているか、パッケージスキャンで定義されているかは関係ありません)。
<context:component-scan>
また、パッケージをスキャンして、アプリケーションコンテキスト内でBeanを検索および登録することも<context:annotation-config>
できます。<context:component-scan>
いくつかの例を使用して、相違点/類似点を示します。
A
タイプが、、の3つのBeanの基本的なセットアップから始めましょう。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
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.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
し、XMLに以下を追加するB
とC
、コンテキストをロードした後に何が得られますか?
<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>
。