it-swarm.it

Differenza tra <context: annotation-config> vs <context: component-scan>

Sto imparando Spring 3 e non riesco a cogliere le funzionalità di <context:annotation-config> e <context:component-scan>.

Da quello che ho letto sembrano gestire diverse annotazioni (@Required, @Autowired etc vs @Component, @Repository, @Service ecc.) Ma anche da quello che ho letto registrano le stesse classi di post processor dei bean.

Per confondermi ancora di più, c'è un attributo annotation-config su <context:component-scan>.

Qualcuno può far luce su questi tag? Ciò che è simile, ciò che è diverso, è sostituito dall'altra, si completano a vicenda, ne ho bisogno uno, entrambi?

634
user938214097

<context:annotation-config> viene utilizzato per attivare le annotazioni nei bean già registrati nel contesto dell'applicazione (indipendentemente dal fatto che siano stati definiti con XML o mediante scansione dei pacchetti).

<context:component-scan> può anche eseguire ciò che <context:annotation-config> fa, ma <context:component-scan> esegue anche la scansione dei pacchetti per trovare e registrare i bean all'interno del contesto dell'applicazione.

Userò degli esempi per mostrare le differenze/somiglianze. 

Iniziamo con una configurazione di base di tre bean di tipo A, B e C, con B e C immessi in 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; 
  }
}

Con la seguente configurazione 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>

Il caricamento del contesto produce il seguente output:

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, questo è l'output atteso. Ma questa primavera è "vecchio stile". Ora abbiamo le annotazioni, quindi usiamo quelle per semplificare l'XML.

Innanzitutto, consente di autorizzare le proprietà bbb e ccc su bean A in questo modo:

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

Questo mi permette di rimuovere le seguenti righe dall'XML:

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

Il mio XML è ora semplificato per questo:

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

Quando carico il contesto, ottengo il seguente risultato:

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

OK, questo è sbagliato! Quello che è successo? Perché le mie proprietà non sono autorizzate?

Bene, le annotazioni sono una bella funzionalità ma da sole non fanno assolutamente nulla. Annotano solo cose. È necessario uno strumento di elaborazione per trovare le annotazioni e fare qualcosa con loro. 

<context:annotation-config> in soccorso. Ciò attiva le azioni per le annotazioni che trova sui bean definiti nello stesso contesto di applicazione in cui è definito esso stesso.

Se cambio il mio XML in questo modo:

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

quando carico il contesto dell'applicazione ottengo il risultato corretto:

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, questo è bello, ma ho rimosso due righe dall'XML e ne ho aggiunto uno. Questa non è una grande differenza. L'idea con le annotazioni è che dovrebbe rimuovere l'XML.

Rimuovere quindi le definizioni XML e sostituirle tutte con annotazioni:

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

Mentre in XML manteniamo questo:

<context:annotation-config />

Carichiamo il contesto e il risultato è ... Niente. Nessun bean viene creato, nessun bean viene avviato automaticamente. Niente!

Questo perché, come ho detto nel primo paragrafo, <context:annotation-config /> funziona solo su bean registrati all'interno del contesto dell'applicazione. Poiché ho rimosso la configurazione XML per i tre bean non è stato creato alcun bean e <context:annotation-config /> non ha "target" su cui lavorare.

Ma questo non rappresenterà un problema per <context:component-scan> che può eseguire la scansione di un pacchetto in cui "target" su cui lavorare. Cambiamo il contenuto della configurazione XML nella seguente voce:

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

Quando carico il contesto, ottengo il seguente risultato:

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

Hmmmm ... manca qualcosa. Perché? 

Se osservi le classi in modo quasi invisibile, class A ha il pacchetto com.yyy ma ho specificato in <context:component-scan> di usare il pacchetto com.xxx, quindi ho completamente perso la mia classe A e ho raccolto solo B e C che si trovano nel pacchetto com.xxx.

Per risolvere questo problema, aggiungo anche questo altro pacchetto:

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

e ora otteniamo il risultato atteso:

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]

E questo è tutto! Ora non hai più definizioni XML, hai annotazioni.

Come ultimo esempio, mantenendo le classi annotate A, B e C e aggiungendo quanto segue all'XML, cosa otterremo dopo aver caricato il contesto?

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

Abbiamo ancora il risultato corretto:

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]

Anche se il bean per la classe A non è ottenuto mediante scansione, gli strumenti di elaborazione sono ancora applicati da <context:component-scan> su tutti i bean registrati nel contesto dell'applicazione, anche per A che è stato registrato manualmente nell'XML.

Ma se avessimo il seguente XML, otterremo dei bean duplicati perché abbiamo specificato sia <context:annotation-config /> che <context:component-scan>?

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

No, nessuna duplicazione, otteniamo nuovamente il risultato atteso:

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]

Questo perché entrambi i tag registrano gli stessi strumenti di elaborazione (<context:annotation-config /> può essere omesso se <context:component-scan> è specificato) ma Spring si occupa di eseguirli una sola volta.

Anche se registri tu stesso gli strumenti di elaborazione più volte, Spring si assicurerà che facciano la loro magia solo una volta; questo 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" />

genererà comunque il seguente risultato:

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, per quanto riguarda il rap. 

Spero che queste informazioni insieme alle risposte di @Tomasz Nurkiewicz e @Sean Patrick Floyd siano tutto ciò che serve per capire come funzionano <context:annotation-config> e <context:component-scan>.

1341
user159088

Ho trovato questo Nice summary di quali annotazioni sono state prese da quali dichiarazioni. Studiandolo scoprirai che <context:component-scan/> riconosce un superset di annotazioni riconosciute da <context:annotation-config/>, vale a dire:

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

Come puoi vedere <context:component-scan/> logicamente estende<context:annotation-config/> con le funzionalità di scansione dei componenti CLASSPATH e Java @Configuration.

160

Spring ti permette di fare due cose:

  1. Autowiring di fagioli
  2. Autodiscovery di fagioli

1. Autowiring
Di solito in applicationContext.xml si definiscono i bean e gli altri bean sono cablati usando i metodi Di costruttori o setter. Puoi collegare i bean usando XML o annotazioni . Se usi annotazioni, devi attivare le annotazioni e devi aggiungere <context:annotation-config /> in applicationContext.xml. Questo semplificherà la struttura Del tag da applicationContext.xml, perché non dovrai collegare manualmente i bean (costruttore o setter). È possibile utilizzare l'annotazione @Autowire ei bean saranno cablati per tipo.

È un passo in avanti per l'escaping della configurazione XML manuale 

2. Autodiscovery
L'autodiscovery semplifica ulteriormente l'XML, nel senso che non è nemmeno necessario aggiungere il tag <bean> in applicationContext.xml. Contrassegni semplicemente i bean specifici con una delle seguenti annotazioni e Spring collegherà automaticamente i bean contrassegnati e le loro dipendenze nel contenitore Spring. Le annotazioni sono le seguenti: @Controller, @Service, @Component, @Repository. Usando <context:component-scan> e puntando il pacchetto base, Spring scoprirà automaticamente e collegherà i componenti al container Spring.


Come conclusione:

  • <context:annotation-config /> è usato per poter usare l'annotazione @Accenduto
  • <context:component-scan /> è usato per determinare la ricerca di bean specifici e il tentativo di autowiring.
85
user2673474

<context:annotation-config> attiva molte annotazioni diverse nei bean, che siano definite in XML o tramite la scansione dei componenti.

<context:component-scan> serve per definire i bean senza usare XML

Per ulteriori informazioni, leggi:

31

La differenza tra i due è davvero semplice !.

<context:annotation-config /> 

Consente di utilizzare annotazioni limitate al cablaggio di proprietà e costruttori di bean !.

Mentre

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

Abilita tutto ciò che <context:annotation-config /> può fare, con l'aggiunta di utilizzare stereotipi, ad es. @Component, @Service, @Repository. Quindi puoi collegare interi bean e non solo ristretti a costruttori o proprietà !. 

28
Sparticles

<context:annotation-config>: Scansione e attivazione di annotazioni per bean già registrati in spring config xml.

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


@Autowired e @Required sono livello di proprietà degli obiettivi quindi il bean deve essere registrato in primavera IOC prima di utilizzare queste annotazioni. Per abilitare queste annotazioni è necessario registrare i rispettivi bean o includere <context:annotation-config />. cioè <context:annotation-config /> funziona solo con i fagioli registrati.

@Required abilita lo strumento di elaborazione RequiredAnnotationBeanPostProcessor
@Autowired abilita lo strumento di elaborazione AutowiredAnnotationBeanPostProcessor

Nota: Annotazione stessa nulla da fare, abbiamo bisogno di un Processing Tool, che è una classe sotto, responsabile del processo core.


@Repository, @Service e @Controller sono @Component, e sono target level level.

<context:component-scan> esegue la scansione del pacchetto e trova e registra i bean, e include il lavoro svolto da <context:annotation-config />.

Migrazione di XML in annotazioni

24
Premraj

Il tag <context:annotation-config> indica a Spring di eseguire la scansione del codebase per la risoluzione automatica dei requisiti di dipendenza delle classi contenenti l'annotazione @Autowired.

Spring 2.5 aggiunge anche il supporto per le annotazioni JSR-250 come @Resource, @PostConstruct e @ PreDestroy.Use di queste annotazioni richiede anche che alcuni BeanPostProcessors vengano registrati all'interno del contenitore Spring. Come sempre, queste possono essere registrate come singole definizioni di bean, ma possono anche essere registrate implicitamente includendo il tag <context:annotation-config> nella configurazione di primavera.

Tratto da Spring documentazione di Annotation Based Configuration


Spring fornisce la capacità di rilevare automaticamente classi "stereotipate" e di registrare BeanDefinitions corrispondenti con ApplicationContext.

Secondo javadoc di org.springframework.stereotype :

Gli stereotipi sono annotazioni che denotano i ruoli di tipi o metodi nell'architettura generale (a livello concettuale, piuttosto che di implementazione). Esempio: @Controller @Service @Repository ecc Questi sono destinati all'uso da parte di strumenti e aspetti (creando un obiettivo ideale per i punti).

Per riconoscere automaticamente tali classi "stereotipo", è necessario il tag <context:component-scan>.

Il tag <context:component-scan> indica anche a Spring di eseguire la scansione del codice per i fagioli iniettabili sotto il pacchetto (e tutti i suoi sotto-pacchetti) specificati.

15
Sachin Sharma
<context:annotation-config>

Solo risolve le annotazioni @Autowired e @Qualifer, questo è tutto riguardo/ Iniezione delle dipendenze , Ci sono altre annotazioni che fanno lo stesso lavoro, penso a come @Inject, ma tutto per risolvere il DI attraverso annotazioni.

Tieni presente che, anche quando hai dichiarato l'elemento <context:annotation-config>, devi dichiarare la tua classe come un bean comunque, ricorda che abbiamo tre opzioni disponibili

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

Ora con

<context:component-scan>

Fa due cose:

  • Esegue la scansione di tutte le classi annotate con @ Component, @Service, @Repository, @Controller e @Configuration e crea un bean
  • Fa lo stesso lavoro di <context:annotation-config>.

Pertanto se dichiari <context:component-scan>, non è più necessario dichiarare anche <context:annotation-config>.

È tutto 

Uno scenario comune è stato ad esempio dichiarare solo un bean tramite XML e risolvere il DI attraverso le annotazioni, ad esempio

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

Abbiamo solo dichiarato i bean, niente su <constructor-arg> e <property>, il DI è configurato nelle loro classi attraverso @Autowired. Significa che i servizi utilizzano @Autowired per i relativi componenti di repository e i repository utilizzano @Autowired per JdbcTemplate, DataSource, ecc.

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

prova con <context:component-scan base-package="..." annotation-config="false"/>, nella tua configurazione @Service, @Repository, @Component funziona bene, ma @ Autowired, @ Resource e @Inject non funziona.

Ciò significa che AutowiredAnnotationBeanPostProcessor non sarà abilitato e il contenitore Spring non elaborerà le annotazioni di Autowiring.

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

L'altro punto importante da notare è che context:component-scan richiama implicitamente context:annotation-config per attivare le annotazioni sui bean. Bene se non vuoi che context:component-scan attivi automaticamente le annotazioni per te, puoi continuare ad impostare l'elemento annotation-config di context:component-scan su false.

Riassumere:

<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

Un tag personalizzato <context:component-scan/> registra lo stesso insieme di definizioni di bean come fa, oltre alla sua responsabilità primaria di analizzare i pacchetti Java e registrare le definizioni dei bean dal classpath.

Se per qualche ragione questa registrazione delle definizioni di bean predefinite deve essere evitata, il modo per farlo è specificare un attributo "annotation-config" aggiuntivo in component-scan, in questo modo:

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

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

0
Abhishek Gaur

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

Questo è usato per dire al contenitore che ci sono classi di bean nel mio pacchetto che scansionano quelle classi di bean. Per scansionare le classi di bean per container in cima al bean, dobbiamo scrivere una delle annotazioni di tipo stereo come segue.

@Component, @Service, @Repository, @Controller

<context:annotation-config />:

Se non vogliamo scrivere esplicitamente il tag bean in XML, allora il contenitore sa se c'è un cablaggio automatico nel bean. Questo è possibile usando l'annotazione @Autowired. dobbiamo informare il contenitore che c'è un cablaggio automatico nel mio bean con context:annotation-config.

0

Come complementare, puoi usare @ComponentScan per usare <context:component-scan> in modo annotazione.

È anche descritto in spring.io

Configura le direttive di scansione dei componenti da utilizzare con le classi @Configuration. Fornisce supporto parallelo all'elemento Spring XML.

Una cosa da notare, se stai usando Spring Boot, @Configuration e @ComponentScan possono essere impliciti usando l'annotazione @SpringBootApplication.

0
Gearon

<context:annotation-config>:

Questo dice a Spring che userò i fagioli Annotated come bean spring e quelli saranno cablati attraverso l'annotazione @Autowired, invece di dichiararli nel file xml di primavera.

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

Questo dice al contenitore di Spring, dove iniziare a cercare quei bean annotati. Qui la primavera cercherà tutti i pacchetti secondari del pacchetto base.

0

puoi trovare maggiori informazioni nel file dello schema di contesto di primavera . seguente è in spring-context-4.3.xsd

<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