<context:annotation-config>
uygulama bağlamında zaten kayıtlı olan fasulyelerde ek açıklamaları etkinleştirmek için kullanılır (XML ile veya paket tarama ile tanımlanmış olmalarına bakılmaksızın).
<context:component-scan>
ayrıca uygulama bağlamında fasulye bulmak ve kaydetmek için paketleri <context:annotation-config>
yapar, ancak <context:component-scan>
tarar.
Farklılıkları / benzerlikleri göstermek için bazı örnekler kullanacağım.
Tip üç fasulye temel kurulum ile başlayalım A
, B
ve C
, ile B
ve C
enjekte ediliyor 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;
}
}
Aşağıdaki XML yapılandırmasıyla:
<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>
Bağlamın yüklenmesi aşağıdaki çıktıyı üretir:
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
Tamam, bu beklenen çıktıdır. Ama bu "eski tarz" Bahar. Şimdi ek açıklamalarımız var, bu yüzden XML'i basitleştirmek için bunları kullanalım.
İlk olarak, fasulye üzerinde bbb
ve ccc
özelliklerini otomatik bağlayalım 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;
}
}
Bu, XML'den aşağıdaki satırları kaldırmama olanak tanır:
<property name="bbb" ref="bBean" />
<property name="ccc" ref="cBean" />
XML'im şimdi basitleştirildi:
<bean id="bBean" class="com.xxx.B" />
<bean id="cBean" class="com.xxx.C" />
<bean id="aBean" class="com.yyy.A" />
Bağlamı yüklediğimde şu çıktıyı alıyorum:
creating bean B: com.xxx.B@5e5a50
creating bean C: com.xxx.C@54a328
creating bean A: com.yyy.A@a3d4cf
Tamam, bu yanlış! Ne oldu? Neden mülklerim otomatik olarak kablolu değil?
Ek açıklamalar güzel bir özelliktir, ancak kendi başlarına hiçbir şey yapmazlar. Sadece bir şeylere not ekliyorlar. Ek açıklamaları bulmak ve onlarla bir şeyler yapmak için bir işleme aracına ihtiyacınız vardır.
<context:annotation-config>
kurtarmak için. Bu, kendisinin tanımlandığı aynı uygulama bağlamında tanımlanan fasulye üzerinde bulduğu ek açıklamaların eylemlerini etkinleştirir.
XML'imi bu şekilde değiştirirsem:
<context:annotation-config />
<bean id="bBean" class="com.xxx.B" />
<bean id="cBean" class="com.xxx.C" />
<bean id="aBean" class="com.yyy.A" />
Uygulama bağlamını yüklediğimde doğru sonucu alıyorum:
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
Tamam, bu güzel, ama XML'den iki satır kaldırdım ve bir satır ekledim. Bu çok büyük bir fark değil. Ek açıklamalarla ilgili fikir, XML'i kaldırması gerektiğidir.
Şimdi XML tanımlarını kaldıralım ve hepsini ek açıklamalarla değiştirelim:
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'deyken bunu yalnızca saklıyoruz:
<context:annotation-config />
Bağlamı yüklüyoruz ve sonuç ... Hiçbir şey. Hiçbir fasulye oluşturulmaz, hiçbir fasulye otomatik olarak bağlanmaz. Hiçbir şey değil!
Çünkü ilk paragrafta söylediğim gibi, <context:annotation-config />
tek uygulama bağlamında kayıtlı fasulye üzerinde çalışır. Üç fasulye için XML yapılandırmasını kaldırdığım için hiçbir fasulye oluşturulmaz ve <context:annotation-config />
üzerinde çalışılacak "hedefler" yoktur.
Ancak bu, <context:component-scan>
bir paketi "hedeflerin" üzerinde çalışabilmesi için tarayabilen bir sorun olmayacaktır . XML yapılandırmasının içeriğini aşağıdaki girişle değiştirelim:
<context:component-scan base-package="com.xxx" />
Bağlamı yüklediğimde şu çıktıyı alıyorum:
creating bean B: com.xxx.B@1be0f0a
creating bean C: com.xxx.C@80d1ff
Hmmmm ... bir şey eksik. Neden?
Eğer derslere closelly bakarsak, sınıf A
paketi vardır com.yyy
ama belirttiğiniz <context:component-scan>
paketi kullanmak com.xxx
bu tamamen benim cevapsız böylece A
sınıf ve sadece aldı B
ve C
hangi Hangi com.xxx
pakete.
Bunu düzeltmek için, bu diğer paketi de ekliyorum:
<context:component-scan base-package="com.xxx,com.yyy" />
ve şimdi beklenen sonucu alıyoruz:
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
Ve bu kadar! Artık XML tanımlarınız yok, ek açıklamalarınız var.
Son bir örnek olarak, açıklamalı sınıfları tutarak A
, B
ve C
biz bağlamı yükledikten sonra neler alacak ve XML aşağıdaki ekleyerek?
<context:component-scan base-package="com.xxx" />
<bean id="aBean" class="com.yyy.A" />
Hala doğru sonucu alıyoruz:
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
Sınıf çekirdeği A
tarama yoluyla elde edilemese bile , işleme araçları , XML'de manuel olarak kaydedilmiş <context:component-scan>
olsa bile uygulama bağlamında kayıtlı tüm çekirdeklere uygulanmaktadır A
.
Aşağıdaki XML varsa Ama, ne biz belirttiğiniz çünkü fasulye çoğaltılır hem alacak <context:annotation-config />
ve <context:component-scan>
?
<context:annotation-config />
<context:component-scan base-package="com.xxx" />
<bean id="aBean" class="com.yyy.A" />
Hayır, yineleme yok, yine beklenen sonucu alıyoruz:
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
Çünkü her iki etiket de aynı işleme araçlarını kaydeder ( belirtilirse <context:annotation-config />
atlanabilir <context:component-scan>
), ancak Spring bunları yalnızca bir kez çalıştırmaya özen gösterir.
İşleme araçlarını birden çok kez kaydettirseniz bile, Spring yine de sihirlerini sadece bir kez yaptıklarından emin olacaktır; bu 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" />
yine de aşağıdaki sonucu oluşturur:
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
Tamam, bu onu hızlandırır.
Umarım bu bilgiler @Tomasz Nurkiewicz ve @Sean Patrick Floyd'un yanıtlarıyla birlikte nasıl <context:annotation-config>
ve nasıl <context:component-scan>
çalıştığını anlamak için ihtiyacınız olan her şeydir
.