Question Différence entre et


J'apprends le printemps 3 et je ne semble pas saisir la fonctionnalité derrière <context:annotation-config> et <context:component-scan>.

D'après ce que j'ai lu, ils semblent gérer différentes annotations (@Required, @Autowired etc vs @Component, @Repository, @Service etc) mais aussi de ce que j'ai lu, ils enregistrent les mêmes classes de post-traitement de bean.

Pour me confondre encore plus, il y a un annotation-config attribuer sur <context:component-scan>.

Quelqu'un peut-il faire la lumière sur ces étiquettes? Qu'est-ce qui est similaire, ce qui est différent, est-ce que l'un est dépassé par l'autre, ils se complètent, ai-je besoin de l'un d'entre eux, les deux?


609
2017-09-14 10:28


origine


Réponses:


<context:annotation-config> est utilisé pour activer les annotations dans les beans déjà enregistrés dans le contexte de l'application (qu'ils aient été définis avec XML ou par analyse de paquets).

<context:component-scan> peut aussi faire quoi <context:annotation-config> fait mais <context:component-scan> analyse également les paquets pour trouver et enregistrer les beans dans le contexte de l'application.

Je vais utiliser quelques exemples pour montrer les différences / similitudes.

Commençons par une configuration de base de trois haricots de type A, B et C, avec B et C étant injecté dans 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; 
  }
}

Avec la configuration XML suivante:

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

Le chargement du contexte produit la sortie suivante:

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, c'est la sortie attendue. Mais c'est "vieux style" printemps. Maintenant, nous avons des annotations, alors utilisons-les pour simplifier le XML.

Premièrement, permet autowire le bbb et ccc propriétés sur le haricot A ainsi:

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

Cela me permet de supprimer les lignes suivantes du XML:

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

Mon XML est maintenant simplifié à ceci:

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

Lorsque je charge le contexte, j'obtiens la sortie suivante:

creating bean B: com.xxx.B@5e5a50
creating bean C: com.xxx.C@54a328
creating bean A: com.yyy.A@a3d4cf

OK, c'est faux! Qu'est-il arrivé? Pourquoi mes propriétés ne sont-elles pas autowired?

Eh bien, les annotations sont une fonctionnalité intéressante, mais par eux-mêmes, ils ne font absolument rien. Ils annotent juste des trucs. Vous avez besoin d'un outil de traitement pour trouver les annotations et faire quelque chose avec eux.

<context:annotation-config> à la rescousse. Cela active les actions pour les annotations qu'il trouve sur les beans définis dans le même contexte d'application où lui-même est défini.

Si je change mon XML à ceci:

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

quand je charge le contexte de l'application, j'obtiens le bon résultat:

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, c'est bien, mais j'ai supprimé deux lignes du XML et ajouté un. Ce n'est pas une très grande différence. L'idée avec des annotations est que c'est censé enlever le XML.

Supprimons les définitions XML et remplaçons-les par des annotations:

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

Alors que dans le XML, nous gardons seulement ceci:

<context:annotation-config />

Nous chargeons le contexte et le résultat est ... Rien. Aucun haricot n'est créé, aucun haricot n'est autofilmé. Rien!

Parce que, comme je l'ai dit au premier paragraphe, <context:annotation-config /> ne fonctionne que sur les beans enregistrés dans le contexte de l'application. Parce que j'ai supprimé la configuration XML pour les trois beans, il n'y a pas de bean créé et <context:annotation-config /> n'a pas de «cibles» à travailler.

Mais ce ne sera pas un problème pour <context:component-scan> qui peut scanner un paquet pour les "cibles" sur lesquelles travailler. Modifions le contenu de la configuration XML dans l'entrée suivante:

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

Lorsque je charge le contexte, j'obtiens la sortie suivante:

creating bean B: com.xxx.B@1be0f0a
creating bean C: com.xxx.C@80d1ff

Hmmmm ... il manque quelque chose. Pourquoi?

Si vous regardez de près les classes, classe A a un paquet com.yyy mais j'ai spécifié dans le <context:component-scan> utiliser le paquet com.xxx donc cela a complètement manqué mon A classe et ramassé seulement B et C qui sont sur le com.xxx paquet.

Pour résoudre ce problème, j'ajoute également cet autre paquet:

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

et maintenant nous obtenons le résultat attendu:

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

Et c'est tout! Maintenant vous n'avez plus de définitions XML, vous avez des annotations.

Comme dernier exemple, conserver les classes annotées A, B et C et en ajoutant ce qui suit au XML, qu'obtiendrons-nous après avoir chargé le contexte?

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

Nous obtenons toujours le bon résultat:

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

Même si le haricot pour la classe A n'est pas obtenu par balayage, les outils de traitement sont toujours appliqués par <context:component-scan> sur tous les haricots enregistrés dans le contexte de l'application, même pour A qui a été enregistré manuellement dans le XML.

Mais si nous avons le XML suivant, aurons-nous des beans dupliqués parce que nous avons spécifié à la fois <context:annotation-config /> et <context:component-scan>?

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

Non, pas de duplication, nous obtenons à nouveau le résultat attendu:

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

En effet, les deux balises enregistrent les mêmes outils de traitement (<context:annotation-config /> peut être omis si <context:component-scan> est spécifié) mais Spring prend soin de les faire fonctionner une seule fois.

Même si vous inscrivez plusieurs fois les outils de traitement, Spring veillera à ce qu'ils ne fassent leur magie qu'une seule fois. ce 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" />

générera toujours le résultat suivant:

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, ça parle de ça.

J'espère que cette information ainsi que les réponses de @Tomasz Nurkiewicz et @Sean Patrick Floyd sont tout ce dont vous avez besoin pour comprendre comment <context:annotation-config> et <context:component-scan> travail.


1289
2017-09-17 17:16



J'ai trouvé ça bien résumé dont les annotations sont relevées par quelles déclarations. En l'étudiant, vous constaterez que <context:component-scan/> reconnaît un surensemble d'annotations reconnues par <context:annotation-config/>, à savoir:

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

Comme vous pouvez le voir <context:component-scan/> logiquement s'étend  <context:annotation-config/> avec l'analyse des composants CLASSPATH et les fonctions Java @Configuration.


156
2017-09-14 10:39



Le printemps vous permet de faire deux choses:

  1. Autowiring de haricots
  2. Autodécouverte des haricots

1. Autowiring
Habituellement dans applicationContext.xml vous définissez les haricots et autres haricots sont câblés en utilisant méthodes constructeur ou setter. Vous pouvez câbler des beans en utilisant XML ou des annotations. Si vous utilisez des annotations, vous devez activer les annotations et vous devez ajouter <context:annotation-config /> dans applicationContext.xml. Cela va simplifier la structure de l'étiquette de applicationContext.xml, car vous n'aurez pas à câbler manuellement les beans (constructeur ou setter). Vous pouvez utiliser @Autowire l'annotation et les haricots seront câblés par type.

Un pas en avant pour échapper à la configuration XML manuelle est

2. Autodiscovery
La découverte automatique simplifie un peu plus le code XML, dans le sens où vous n'avez même pas besoin d'ajouter <bean> faire applicationContext.xml. Vous marquez simplement les haricots spécifiques avec l'une des annotations suivantes et Spring câblera automatiquement les haricots marqués et leurs dépendances dans le conteneur Spring. Les annotations sont les suivantes: @Manette, @Un service, @Composant, @Dépôt. En utilisant <context:component-scan> et en pointant le paquet de base, Spring va automatiquement découvrir et câbler les composants dans le conteneur Spring.


Comme conclusion:

  • <context:annotation-config /> est utilisé pour pouvoir utiliser @Autowired annotation
  • <context:component-scan /> est utilisé pour déterminer la recherche de haricots spécifiques et tentative d'autowiring.

81
2017-08-12 02:29



<context:annotation-config> active de nombreuses annotations différentes dans les beans, qu'elles soient définies en XML ou via l'analyse des composants.

<context:component-scan> est pour définir des beans sans utiliser XML

Pour plus d'informations, lisez:


29
2017-09-14 10:41



La différence entre les deux est vraiment simple!

<context:annotation-config /> 

Vous permet d'utiliser des annotations réservées au câblage des propriétés et des constructeurs uniquement de beans !.

Tandis que

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

Active tout ce qui <context:annotation-config /> peut faire, avec l'ajout de l'utilisation de stéréotypes par exemple .. @Component, @Service , @Repository. Ainsi, vous pouvez câbler des grains entiers et pas seulement des constructeurs ou des propriétés!


27
2017-08-01 22:29



<context:annotation-config>: Analyse et activation des annotations pour les beans déjà enregistrés dans Spring Config xml.

<context:component-scan>: Enregistrement de Bean + <context:annotation-config>


@Autowired et @Required sont cible le niveau de la propriété si le haricot devrait enregistrer au printemps IOC avant d'utiliser ces annotations. Pour activer ces annotations doivent soit enregistrer les haricots respectifs ou inclure <context:annotation-config />. c'est à dire. <context:annotation-config /> fonctionne uniquement avec les haricots enregistrés.

@Champs obligatoires permet RequiredAnnotationBeanPostProcessor  outil de traitement
@Autowired permet AutowiredAnnotationBeanPostProcessor outil de traitement

Remarque: Annotation elle-même rien à faire, nous avons besoin d'un Outil de traitement, qui est une classe en dessous, responsable du processus de base.


@Repository, @Service et @Controller sont @Component, et ils cible le niveau de la classe.

<context:component-scan> il scanne le paquet et trouve et enregistre les haricots, et il comprend le travail effectué par <context:annotation-config />.


22
2018-01-02 02:22



le <context:annotation-config> tag indique à Spring d'analyser la base de code pour résoudre automatiquement les exigences de dépendance des classes contenant l'annotation @Autowired.

Spring 2.5 ajoute également la prise en charge des annotations JSR-250 telles que @Resource, @PostConstruct et @ PreDestroy. L'utilisation de ces annotations nécessite également que certains BeanPostProcessors soient enregistrés dans le conteneur Spring. Comme toujours, ils peuvent être enregistrés en tant que définitions de beans individuelles, mais ils peuvent également être enregistrés implicitement en incluant <context:annotation-config> étiquette dans la configuration de ressort.

Tiré de la documentation de printemps de Configuration basée sur l'annotation


Spring offre la possibilité de détecter automatiquement les classes "stéréotypées" et d'enregistrer les définitions Bean correspondantes avec ApplicationContext.

Selon javadoc de org.springframework.stereotype:

Les stéréotypes sont des annotations indiquant les rôles des types ou des méthodes dans l'architecture globale (au niveau conceptuel plutôt que de l'implémentation). Exemple: @Controller @Service @Repository etc. Ceux-ci sont destinés à être utilisés par des outils et des aspects (en faisant une cible idéale pour les coupures de points).

Pour détecter automatiquement ces classes de "stéréotype", <context:component-scan> tag est requis.

le <context:component-scan> tag indique également à Spring d'analyser le code pour les beans injectables sous le paquet (et tous ses sous-paquets) spécifiés.


15
2017-08-31 09:08



<context:annotation-config>

Seulement résout les annotations @Autowired et @Qualifer, c'est tout sur le Injection de dépendance, Il existe d'autres annotations qui font le même travail, je pense que @Inject, mais tout à propos de résoudre DI à travers des annotations.

Soyez conscient, même lorsque vous avez déclaré <context:annotation-config> élément, vous devez déclarer votre classe comment un haricot de toute façon, rappelez-vous que nous avons trois options disponibles

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

Maintenant avec

<context:component-scan>

Il fait deux choses:

  • Il scanne toutes les classes annotées avec @Component, @Service, @Repository, @Controller et @Configuration et créer un haricot
  • Il fait le même travail comment <context:annotation-config> Est-ce que.

Par conséquent, si vous déclarez <context:component-scan>, n'est plus nécessaire déclarer <context:annotation-config> aussi.

C'est tout

Un scénario courant était par exemple de déclarer uniquement un bean via XML et de résoudre le DI via des annotations, par exemple

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

Nous avons seulement déclaré les haricots, rien sur <constructor-arg> et <property>, le DI est configuré dans leurs propres classes via @Autowired. Cela signifie que les services utilisent @Autowired pour leurs composants Repositories et que les référentiels utilisent @Autowired pour les composants JdbcTemplate, DataSource, etc.


9
2018-06-06 13:28