<context:annotation-config>
використовується для активації приміток у квасолі, вже зареєстрованій у контексті програми (незалежно від того, чи були вони визначені за допомогою XML або шляхом сканування пакетів).
<context:component-scan>
може також робити те, що <context:annotation-config>
робить, але <context:component-scan>
також сканує пакети, щоб знайти та зареєструвати боби в контексті програми.
Я буду використовувати кілька прикладів, щоб показати відмінності / схожість.
Почне з базової налаштуванням трьох квасолі типу 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
Гаразд, це очікуваний вихід. Але це весна "старого стилю". Тепер у нас є примітки, тому давайте зможемо використовувати ці для спрощення XML.
По-перше, давайте надіслати автоматичне з'єднання 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>
на допомогу. Це активує дії для анотацій, які він знаходить на квасолі, визначеній у тому самому контексті програми, де визначено саме це.
Якщо я зміню свій 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
Добре, це добре, але я видалив два ряди з XML і додав один. Це не дуже велика різниця. Ідея з примітками полягає в тому, що слід видалити 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 />
Ми завантажуємо контекст, і результат ... Нічого. Не створюється квасоля, жодна квасоля не є автопровідною. Нічого!
Це тому, що, як я вже говорив у першому пункті, <context:annotation-config />
єдині роботи на квасолі, зареєстровані в контексті заявки. Оскільки я видалив конфігурацію XML для трьох бобів, боб не створений і <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
, 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
не отримана шляхом сканування, інструменти обробки все ще застосовуються <context:component-scan>
на всіх бобах, зареєстрованих у контексті програми, навіть для A
яких було зареєстровано вручну в XML.
Але що, якщо у нас є наступний 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 опікується їх запуском лише один раз.
Навіть якщо ви реєструєте інструменти для обробки самостійно кілька разів, Spring все одно переконається, що вони виконують свою магію лише один раз; ця 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>
працювати.