it-swarm.com.de

Unterschied zwischen <Kontext: Annotation-Config> und <Kontext: Komponentenscan>

Ich lerne Spring 3 und scheine die Funktionalität von <context:annotation-config> und <context:component-scan> nicht zu verstehen.

Nach dem, was ich gelesen habe, scheinen sie unterschiedliche Anmerkungen zu behandeln (@Required, @Autowired etc vs. @Component, @Repository, @Service usw.), aber auch von dem, was ich gelesen habe, dass sie die gleichen Bean-Post-Prozessor-Klassen registrieren.

Um mich noch mehr zu verwirren, gibt es ein annotation-config-Attribut in <context:component-scan>.

Kann jemand etwas Licht auf diese Tags werfen? Was ist ähnlich, was ist anders, ist einer von dem anderen abgelöst, sie ergänzen sich, brauche ich einen von beiden?

634
user938214097

<context:annotation-config> wird verwendet, um Annotationen in Beans zu aktivieren, die bereits im Anwendungskontext registriert sind (unabhängig davon, ob sie mit XML oder durch das Durchsuchen von Paketen definiert wurden).

<context:component-scan> kann auch das, was <context:annotation-config> tut, aber <context:component-scan> durchsucht auch Pakete, um Beans im Anwendungskontext zu finden und zu registrieren.

Ich werde einige Beispiele verwenden, um die Unterschiede/Ähnlichkeiten aufzuzeigen. 

Beginnen wir mit einem Grundsetup von drei Beans vom Typ A, B und C, wobei B und C in A eingefügt werden.

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; 
  }
}

Mit der folgenden XML-Konfiguration:

<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>

Das Laden des Kontextes erzeugt die folgende Ausgabe:

creating bean B: [email protected]
creating bean C: [email protected]
creating bean A: [email protected]
setting A.bbb with [email protected]
setting A.ccc with [email protected]

OK, das ist die erwartete Ausgabe. Aber das ist "alter Stil" Frühling. Jetzt haben wir Anmerkungen, also können wir diese nutzen, um das XML zu vereinfachen.

Zuerst lassen wir die bbb- und ccc-Eigenschaften der Bean A wie folgt autowire:

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;
  }
}

Dadurch kann ich die folgenden Zeilen aus der XML-Datei entfernen:

<property name="bbb" ref="bBean" />
<property name="ccc" ref="cBean" />

Mein XML ist jetzt so vereinfacht:

<bean id="bBean" class="com.xxx.B" />
<bean id="cBean" class="com.xxx.C" />
<bean id="aBean" class="com.yyy.A" />

Wenn ich den Kontext lade, erhalte ich folgende Ausgabe:

creating bean B: [email protected]
creating bean C: [email protected]
creating bean A: [email protected]

OK, das ist falsch! Was ist passiert? Warum sind meine Immobilien nicht automatisch belegt?

Nun, Annotationen sind eine schöne Funktion, aber für sich genommen machen sie gar nichts. Sie kommentieren einfach Sachen. Sie benötigen ein Verarbeitungstool, um die Anmerkungen zu finden und etwas damit zu tun. 

<context:annotation-config> zur Rettung. Dadurch werden die Aktionen für die Anmerkungen aktiviert, die auf den Beans gefunden werden, die in demselben Anwendungskontext definiert sind, in dem sie selbst definiert sind.

Wenn ich mein XML so umstelle:

<context:annotation-config />
<bean id="bBean" class="com.xxx.B" />
<bean id="cBean" class="com.xxx.C" />
<bean id="aBean" class="com.yyy.A" />

wenn ich den Anwendungskontext lade, erhalte ich das richtige Ergebnis:

creating bean B: [email protected]
creating bean C: [email protected]
creating bean A: [email protected]
setting A.bbb with [email protected]
setting A.ccc with [email protected]

OK, das ist Nizza, aber ich habe zwei Zeilen aus der XML-Datei entfernt und eine hinzugefügt. Das ist kein großer Unterschied. Die Idee bei Anmerkungen ist, dass XML entfernt werden soll.

Also entfernen wir die XML-Definitionen und ersetzen sie alle mit Anmerkungen:

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;
  }
}

Im XML behalten wir nur folgendes:

<context:annotation-config />

Wir laden den Kontext und das Ergebnis ist ... Nichts. Es werden keine Beans erstellt, keine Beans werden automatisch belegt. Nichts!

Das liegt daran, dass <context:annotation-config />, wie ich im ersten Absatz gesagt habe, nur für Beans funktioniert, die im Anwendungskontext registriert sind. Da ich die XML-Konfiguration für die drei Beans entfernt habe, wird keine Bean erstellt, und <context:annotation-config /> hat keine "Ziele", an denen gearbeitet werden kann.

Dies ist jedoch kein Problem für <context:component-scan>, das ein Paket nach "Zielen" scannen kann, an denen gearbeitet werden kann. Ändern Sie den Inhalt der XML-Konfiguration in den folgenden Eintrag:

<context:component-scan base-package="com.xxx" />

Wenn ich den Kontext lade, erhalte ich folgende Ausgabe:

creating bean B: [email protected]
creating bean C: [email protected]

Hmmmm ... etwas fehlt. Warum? 

Wenn Sie sich die Klassen genau ansehen, hat die Klasse A das Paket com.yyy, aber ich habe im <context:component-scan> angegeben, dass das Paket com.xxx verwendet werden soll. Diese Klasse hat also meine A-Klasse komplett verpasst und nur B und C aufgenommen, die sich auf dem com.xxx-Paket befinden.

Um dies zu beheben, füge ich dieses andere Paket hinzu:

<context:component-scan base-package="com.xxx,com.yyy" />

und jetzt bekommen wir das erwartete Ergebnis:

creating bean B: [email protected]
creating bean C: [email protected]
creating bean A: [email protected]
setting A.bbb with [email protected]
setting A.ccc with [email protected]

Und das ist es! Jetzt haben Sie keine XML-Definitionen mehr, Sie haben Anmerkungen.

Als letztes Beispiel: Behalten Sie die annotierten Klassen A, B und C bei, und fügen Sie der XML Folgendes hinzu: Was erhalten wir nach dem Laden des Kontexts?

<context:component-scan base-package="com.xxx" />
<bean id="aBean" class="com.yyy.A" />

Wir bekommen immer noch das richtige Ergebnis:

creating bean B: [email protected]
creating bean C: [email protected]
creating bean A: [email protected]
setting A.bbb with [email protected]
setting A.ccc with [email protected]

Selbst wenn das Bean für die Klasse A nicht durch Scannen abgerufen wird, werden die Verarbeitungstools weiterhin von <context:component-scan> auf alle registrierten Beans angewendet im Anwendungskontext, selbst für A, das manuell in der XML-Datei registriert wurde.

Was aber, wenn wir das folgende XML haben, erhalten wir doppelte Beans, weil wir sowohl <context:annotation-config /> als auch <context:component-scan> angegeben haben?

<context:annotation-config />
<context:component-scan base-package="com.xxx" />
<bean id="aBean" class="com.yyy.A" />

Nein, keine Duplikationen, wir bekommen wieder das erwartete Ergebnis:

creating bean B: [email protected]
creating bean C: [email protected]
creating bean A: [email protected]
setting A.bbb with [email protected]
setting A.ccc with [email protected]

Das liegt daran, dass beide Tags dieselben Verarbeitungswerkzeuge registrieren (<context:annotation-config /> kann weggelassen werden, wenn <context:component-scan> angegeben ist), Spring kümmert sich jedoch nur darum, sie nur einmal auszuführen.

Selbst wenn Sie die Verarbeitungswerkzeuge mehrmals selbst registrieren, stellt Spring sicher, dass sie nur einmal ihre Zauberei ausführen. dieses 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" />

erzeugt immer noch folgendes Ergebnis:

creating bean B: [email protected]
creating bean C: [email protected]
creating bean A: [email protected]
setting A.bbb with [email protected]
setting A.ccc with [email protected]

OK, das ungefähr raps es. 

Ich hoffe, diese Informationen zusammen mit den Antworten von @Tomasz Nurkiewicz und @Sean Patrick Floyd sind alles, was Sie benötigen, um zu verstehen, wie <context:annotation-config> und <context:component-scan> funktionieren.

1341
user159088

Ich fand diese Nice Zusammenfassung von welcher Annotationen von welchen Deklarationen abgeholt werden. Wenn Sie es studieren, werden Sie feststellen, dass <context:component-scan/> eine übergeordnete Menge von Anmerkungen erkennt, die von <context:annotation-config/> erkannt werden, und zwar:

  • @Component, @Service, @Repository, @Controller, @Endpoint
  • @Configuration, @Bean, @Lazy, @Scope, @Order, @Primary, @Profile, @DependsOn, @Import, @ImportResource

Wie Sie sehen, <context:component-scan/> logisch erweitert<context:annotation-config/> mit CLASSPATH-Komponentenscan und Java @Configuration-Funktionen.

160

Im Frühling können Sie zwei Dinge tun:

  1. Autowiring von Bohnen
  2. Autodiscovery von Bohnen

1. Autowiring
Normalerweise definieren Sie in applicationContext.xml Beans, und andere Beans werden mit Hilfe von Konstruktor- oder Setter-Methoden verbunden. Sie können Beans mit Hilfe von XML oder Annotationen verdrahten. Falls Sie Annotationen verwenden, müssen Sie Annotationen aktivieren und in applicationContext.xml<context:annotation-config /> hinzufügen. Dies vereinfacht die Struktur des Tags von applicationContext.xml, da Sie keine Beans (Konstruktor oder Setter) manuell verbinden müssen. Sie können die @Autowire-Annotation verwenden und die Beans werden nach Typ verkabelt.

Ein Schritt nach vorne, um die manuelle XML-Konfiguration zu umgehen, ist 

2. Autodiscovery
Die automatische Erkennung vereinfacht das XML noch einen Schritt weiter, in dem Sinne, dass Sie nicht einmal den Tag <bean> in applicationContext.xml hinzufügen müssen. Sie müssen nur die jeweiligen Beans mit einer der folgenden Anmerkungen markieren, und Spring führt die markierten Beans und ihre Abhängigkeiten automatisch in den Spring-Container. Die Anmerkungen lauten wie folgt: @Controller, @Service, @Component, @Repository. Wenn Sie <context:component-scan> verwenden und das Basispaket zeigen, erkennt Spring die Komponenten automatisch und verbindet sie mit dem Spring-Container.


Als Schlussfolgerung:

  • <context:annotation-config /> wird verwendet, um die Annotation @Autowired verwenden zu können
  • <context:component-scan /> wird verwendet, um die Suche nach __. spezifischen Beans und den Versuch der automatischen Einstellung zu ermitteln.
85
user2673474

<context:annotation-config> aktiviert viele verschiedene Annotationen in Beans, unabhängig davon, ob sie in XML oder durch Komponentenscan definiert sind.

<context:component-scan> dient zum Definieren von Beans ohne Verwendung von XML

Für weitere Informationen lesen Sie:

31

Der Unterschied zwischen den beiden ist wirklich einfach!.

<context:annotation-config /> 

Ermöglicht die Verwendung von Anmerkungen, die auf die Verdrahtung von Eigenschaften und Konstruktoren nur von Beans beschränkt sind.

Wohingegen

<context:component-scan base-package="org.package"/> 

Aktiviert alles, was <context:annotation-config /> möglich ist, wobei Stereotypen hinzugefügt werden, z. B. .. @Component, @Service, @Repository. So können Sie ganze Beans verdrahten und nicht nur auf Konstruktoren oder Eigenschaften beschränkt sein. 

28
Sparticles

<context:annotation-config>: Scannen und Aktivieren von Anmerkungen für bereits registrierte Beans in spring config xml.

<context:component-scan>: Bean-Registrierung + <context:annotation-config>


@Autowired und @Required sind Zieleigenschaftsebene, so dass sich Bean im Frühjahr IOC registrieren sollte, bevor diese Anmerkungen verwendet werden. Um diese Annotationen zu aktivieren, müssen Sie entweder die entsprechenden Beans registrieren oder <context:annotation-config /> einfügen. Das heißt, <context:annotation-config /> arbeitet nur mit registrierten Beans.

@Required aktiviert das Verarbeitungswerkzeug RequiredAnnotationBeanPostProcessor
@Autowired aktiviert das Verarbeitungswerkzeug AutowiredAnnotationBeanPostProcessor

Anmerkung: Anmerkung selbst nichts zu tun, wir benötigen ein Processing Tool, eine Klasse darunter, die für den Kernprozess verantwortlich ist.


@Repository, @Service und @Controller sind @Component und sie sind Zielklassenebene.

<context:component-scan> scannt das Paket und findet und registriert die Beans und enthält die von <context:annotation-config /> geleistete Arbeit.

Migrieren von XML zu Anmerkungen

24
Premraj

Das <context:annotation-config>-Tag weist Spring an, die Codebasis zu scannen, um die Abhängigkeitsanforderungen der Klassen, die die @Autowired-Annotation enthalten, automatisch aufzulösen.

Spring 2.5 fügt auch Unterstützung für JSR-250-Annotationen wie @Resource, @PostConstruct und @ PreDestroy hinzu. Die Verwendung dieser Annotationen erfordert auch die Registrierung bestimmter BeanPostProcessors im Spring-Container. Diese können wie immer als individuelle Bean-Definitionen registriert werden, sie können jedoch auch implizit registriert werden, indem das <context:annotation-config>-Tag in die Federkonfiguration aufgenommen wird.

Aus der Spring-Dokumentation von Annotation Based Configuration


Spring bietet die Möglichkeit, stereotype Klassen automatisch zu erkennen und entsprechende BeanDefinitions mit ApplicationContext zu registrieren.

Gemäß javadoc von org.springframework.stereotype :

Stereotypen sind Annotationen, die die Rollen von Typen oder Methoden in der Gesamtarchitektur (auf konzeptioneller Ebene und nicht auf Implementierungsebene) bezeichnen. Beispiel: @Controller @Service @Repository usw .. Diese sind für die Verwendung durch Werkzeuge und Aspekte vorgesehen (ein ideales Ziel für Punktschnitte).

Um solche 'Stereotyp'-Klassen automatisch zu erkennen, ist das <context:component-scan>-Tag erforderlich.

Das <context:component-scan>-Tag weist Spring außerdem an, den Code für injizierbare Beans unter dem angegebenen Paket (und allen angegebenen Unterpaketen) zu scannen.

15
Sachin Sharma
<context:annotation-config>

Nur löst die @Autowired- und @Qualifer-Annotationen auf, das ist alles, es geht um die Dependency Injection , Es gibt andere Annotationen, die den gleichen Job machen, denke ich, @Inject, aber alle über DI Anmerkungen.

Seien Sie sich bewusst, auch wenn Sie das <context:annotation-config>-Element deklariert haben, Sie müssen Ihre Klasse angeben, wie ein Bean trotzdem ist. Denken Sie daran, wir haben drei Optionen

  • XML: <bean> 
  • @Anmerkungen: @Component, @Service, @Repository, @Controller 
  • JavaConfig: @Configuration, @Bean

Jetzt mit

<context:component-scan>

Es macht zwei Dinge:

  • Es scannt alle mit @ Component, @Service, @Repository, @Controller und @Configuration annotierten Klassen und erstellt ein Bean
  • Es erledigt den gleichen Job wie <context:annotation-config>.

Wenn Sie also <context:component-scan> angeben, müssen Sie auch <context:annotation-config> nicht mehr angeben.

Das ist alles 

Ein häufiges Szenario war zum Beispiel, dass nur eine Bean über XML deklariert und die DI beispielsweise durch Anmerkungen aufgelöst wird

<bean id="serviceBeanA" class="com.something.CarServiceImpl" />
<bean id="serviceBeanB" class="com.something.PersonServiceImpl" />
<bean id="repositoryBeanA" class="com.something.CarRepository" />
<bean id="repositoryBeanB" class="com.something.PersonRepository" />

Wir haben nur die Beans deklariert, nichts über <constructor-arg> und <property>, das DI wird in eigenen Klassen über @Autowired konfiguriert. Dies bedeutet, dass die Services @Autowired für ihre Repository-Komponenten verwenden und die Repositorys @Autowired für die Komponenten JdbcTemplate, DataSource usw..

10
Manuel Jordan
<context:component-scan /> implicitly enables <context:annotation-config/>

versuchen Sie es mit <context:component-scan base-package="..." annotation-config="false"/>, in Ihrer Konfiguration @Service, @Repository, @Component funktioniert gut, aber @ Autowired, @ Resource und @Inject funktionieren nicht.

Dies bedeutet, dass AutowiredAnnotationBeanPostProcessor nicht aktiviert ist und der Spring-Container die Anmerkungen zur automatischen Einstellung nicht verarbeitet.

6
Lovababu
<context:annotation-config/> <!-- is used to activate the annotation for beans -->
<context:component-scan base-package="x.y.MyClass" /> <!-- is for the Spring IOC container to look for the beans in the base package. -->

Der andere wichtige Punkt ist, dass context:component-scan implizit den context:annotation-config aufruft, um die Anmerkungen zu Beans zu aktivieren. Wenn Sie nicht möchten, dass context:component-scan Annotationen implizit für Sie aktiviert, können Sie das Annotation-config-Element des context:component-scan auf false setzen.

Zusammenfassen:

<context:annotation-config/> <!-- activates the annotations --> 
<context:component-scan base-package="x.y.MyClass" /> <!-- activates the annotations + register the beans by looking inside the base-package -->
5
Abdullah Khan

Ein benutzerdefiniertes <context:component-scan/>-Tag registriert die gleiche Gruppe von Bean-Definitionen, die nicht von seiner primären Verantwortung für das Scannen der Java-Pakete und das Registrieren von Bean-Definitionen aus dem Klassenpfad übernommen wird.

Wenn aus irgendeinem Grund diese Registrierung von Standard-Bean-Definitionen vermieden werden soll, können Sie dazu ein zusätzliches Attribut "annotation-config" im Komponentenscan angeben:

<context:component-scan basePackages="" annotation-config="false"/>

Referenz: http://www.Java-allandsundry.com/2012/12/contextcomponent-scan-contextannotation.html

0
Abhishek Gaur

<context:component-scan base-package="package name" />:

Dies wird verwendet, um dem Container mitzuteilen, dass Bean-Klassen in meinem Paket enthalten sind, um diese Bean-Klassen zu durchsuchen. Um Bean-Klassen nach Container auf dem Bean zu scannen, müssen Sie eine der Stereotypanmerkungen wie folgt schreiben.

@Component, @Service, @Repository, @Controller

<context:annotation-config />:

Wenn wir das Bean-Tag nicht explizit in XML schreiben möchten, weiß der Container, ob das Bean eine automatische Verdrahtung hat. Dies ist durch die Verwendung der Annotation @Autowired möglich. Wir müssen dem Container mitteilen, dass es in meinem Bean eine automatische Verdrahtung durch context:annotation-config gibt.

0

Ergänzend können Sie @ComponentScan verwenden, um <context:component-scan> als Anmerkung zu verwenden.

Es ist auch unter spring.io beschrieben.

Konfiguriert Komponenten-Scan-Anweisungen für die Verwendung mit @ Configuration-Klassen. Bietet Unterstützung parallel zum Spring XML-Element.

Wenn Sie Spring Boot verwenden, sollten Sie beachten, dass @Configuration und @ComponentScan durch die Verwendung der Annotation @SpringBootApplication impliziert werden können.

0
Gearon

<context:annotation-config>:

Dies sagt Spring, dass ich annotierte Beans als Spring Bean verwenden werde und diese würden durch @Autowired Annotation verbunden werden, anstatt im Frühjahr die config-XML-Datei zu deklarieren.

<context:component-scan base-package="com.test...">

Dies teilt dem Spring-Container mit, wo er anfangen soll, diese kommentierten Beans zu suchen. Hier durchsucht spring alle Unterpakete des Basispakets.

0

weitere Informationen finden Sie in der Spring-Kontextschemadatei . Folgendes ist in Spring-Context-4.3.xsd enthalten

<conxtext:annotation-config />
Activates various annotations to be detected in bean classes: Spring's @Required and
@Autowired, as well as JSR 250's @PostConstruct, @PreDestroy and @Resource (if available),
JAX-WS's @WebServiceRef (if available), EJB 3's @EJB (if available), and JPA's
@PersistenceContext and @PersistenceUnit (if available). Alternatively, you may
choose to activate the individual BeanPostProcessors for those annotations.

Note: This tag does not activate processing of Spring's @Transactional or EJB 3's
@TransactionAttribute annotation. Consider the use of the <tx:annotation-driven>
tag for that purpose.
<context:component-scan>
Scans the classpath for annotated components that will be auto-registered as
Spring beans. By default, the Spring-provided @Component, @Repository, @Service, @Controller, @RestController, @ControllerAdvice, and @Configuration stereotypes    will be detected.

Note: This tag implies the effects of the 'annotation-config' tag, activating @Required,
@Autowired, @PostConstruct, @PreDestroy, @Resource, @PersistenceContext and @PersistenceUnit
annotations in the component classes, which is usually desired for autodetected components
(without external configuration). Turn off the 'annotation-config' attribute to deactivate
this default behavior, for example in order to use custom BeanPostProcessor definitions
for handling those annotations.

Note: You may use placeholders in package paths, but only resolved against system
properties (analogous to resource paths). A component scan results in new bean definitions
being registered; Spring's PropertySourcesPlaceholderConfigurer will apply to those bean
definitions just like to regular bean definitions, but it won't apply to the component
scan settings themselves.
0
coffeenjava