Différence entre <context: annotation-config> et <context: component-scan>


691

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

D'après ce que je l' ai lu , ils semblent gérer différentes annotations ( @Required, @Autowiredetc vs @Component, @Repository, @Serviceetc.), mais aussi de ce que j'ai lu , ils enregistrent le même processeur post haricots classes.

Pour me confondre encore plus, il y a un annotation-config attribut 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 remplacé par l'autre, ils se complètent, ai-je besoin de l'un d'eux, des deux?



pour résumer: utiliser component-scanautant que possible.
Jerry Chin

Réponses:


1420

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

<context:component-scan>peut également faire ce qu'il <context:annotation-config>fait mais <context:component-scan>analyse également les packages pour trouver et enregistrer des 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 grains de type A, Bet C, avec Bet Cinjecté 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 le printemps "à l'ancienne". Maintenant que nous avons des annotations, utilisons-les pour simplifier le XML.

Tout d'abord, permet de câbler automatiquement les propriétés bbbet cccsur le bean Acomme ceci:

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 câblées automatiquement?

Eh bien, les annotations sont une fonctionnalité intéressante, mais en elles-mêmes, elles 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 elles.

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

lorsque 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 j'en ai ajouté une. Ce n'est pas une très grande différence. L'idée avec des annotations est qu'il est censé supprimer le XML.

Supprimons donc les définitions XML et remplaçons-les toutes 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;
  }
}

Dans le XML, nous ne gardons que ceci:

<context:annotation-config />

Nous chargeons le contexte et le résultat est ... Rien. Aucun bean n'est créé, aucun bean n'est câblé automatiquement. Rien!

En effet, comme je l'ai dit dans le premier paragraphe, les <context:annotation-config />seuls travaux sur les beans enregistrés dans le contexte de l'application. Parce que j'ai supprimé la configuration XML pour les trois beans, aucun bean n'a été créé et <context:annotation-config />n'a pas de "cibles" sur lesquelles travailler.

Mais ce ne sera pas un problème pour <context:component-scan>lequel peut analyser un package 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, la classe Aa un package, com.yyymais j'ai spécifié dans le <context:component-scan>package à utiliser, com.xxxdonc cela a complètement manqué ma Aclasse et n'a repris que Bet Cqui sont sur lecom.xxx package.

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

<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, en gardant les classes annotées A, Bet Cet en ajoutant ce qui suit au XML, ce que nous obtiendrons après le chargement du 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 bean pour la classe An'est pas obtenu par l'analyse, les outils de traitement sont toujours appliqués par <context:component-scan>sur tous les beans enregistrés dans le contexte de l'application, même pourA qui ont été enregistrés manuellement dans le XML.

Mais que se passe-t-il si nous avons le XML suivant, obtiendrons-nous des beans dupliqués parce que nous avons spécifié les deux <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 doublons, 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 />peuvent être omis si <context:component-scan>spécifié), mais Spring se charge de les exécuter une seule fois.

Même si vous enregistrez vous-même les outils de traitement plusieurs fois, Spring s'assurera qu'ils ne font 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 ces informations 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>travailler.


8
Citation: "<context: annotation-config /> peut être omis si <context: component-scan> est spécifié". Pourquoi utiliser alors annotation-config? Pourquoi existe-t-il?
CodeClimber

2
Très bonne réponse! Rien de tel qu'un court exemple clair avec une description concise. Compris le tout en une seule lecture.
Jigish

19
Je souhaite que vous ayez écrit tout le manuel du printemps! Meilleure explication sur tout ce qui concerne la confusion de Spring Framework. Merci.
eskalera

7
Explication si simple et exceptionnelle. En plus d'obtenir la réponse, j'ai également appris une bonne façon de dire les choses :)
Amir Al

2
Votre style d'écriture est très facile à comprendre pour un débutant. J'espère que vous pourrez écrire un livre sur le printemps de base. Je promets de l'acheter.
emeraldhieu

167

J'ai trouvé ce joli résumé dont les annotations sont captées par quelles déclarations. En l'étudiant, vous constaterez que <context:component-scan/>reconnaît un surensemble d'annotations reconnu 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, il s’étend<context:component-scan/> logiquement avec l’analyse des composants CLASSPATH et les fonctionnalités Java @Configuration. <context:annotation-config/>


16
@Tomasz link down :(
Anand Rockzz

95

Le printemps vous permet de faire deux choses:

  1. Câblage automatique des haricots
  2. Découverte automatique des haricots

1. Câblage automatique
Habituellement, dans applicationContext.xml, vous définissez les beans et les autres beans sont câblés à l'aide de méthodes de constructeur ou de définition. Vous pouvez câbler des beans à l'aide de XML ou d'annotations. Si vous utilisez des annotations, vous devez activer les annotations et vous devez ajouter <context:annotation-config />dans applicationContext.xml . Cela simplifiera la structure de la balise de applicationContext.xml , car vous n'aurez pas à câbler manuellement les beans (constructeur ou setter). Vous pouvez utiliser des @Autowireannotations et les beans seront câblés par type.

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

2. Découverte
automatique La découverte automatique simplifie le XML encore plus loin, dans le sens où vous n'avez même pas besoin d'ajouter la <bean>balise dans applicationContext.xml . Vous marquez simplement les beans spécifiques avec l'une des annotations suivantes et Spring connectera automatiquement les beans marqués et leurs dépendances au conteneur Spring. Les annotations sont les suivantes: @Controller , @Service , @Component , @Repository . En utilisant <context:component-scan>et en pointant le package de base, Spring détecte automatiquement et connecte les composants dans le conteneur Spring.


Comme conclusion:

  • <context:annotation-config />est utilisé pour pouvoir utiliser l' annotation @Autowired
  • <context:component-scan /> est utilisé pour déterminer la recherche de beans spécifiques et la tentative de câblage automatique.

1
Est-il possible d'utiliser l'analyse des composants mais pas la configuration d'annotation d'une manière ou d'une autre?
Koray Tugay

Utilisez annotation-config = "false" dans le contexte: balise annotation-config.
Sara

38

<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> sert à définir des beans sans utiliser XML

Pour plus d'informations, lisez:


Pouvez-vous expliquer davantage? Si j'utilise, <context:component-scan>je ne pourrai pas remplacer la définition de bean en utilisant XML?
user938214097

@ user938214097 vous pouvez définir des beans soit en XML soit par des annotations avec l'analyse des composants
Sean Patrick Floyd

Est-ce suffisant d'utiliser le <context:component-scan>? Dois-je perdre quelque chose si je n'utilise pas le <context:annotation-config>?
user938214097

@Tomasz semble avoir répondu que
Sean Patrick Floyd

31

La différence entre les deux est vraiment simple!.

<context:annotation-config /> 

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

Tandis que

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

Permet tout ce qui <context:annotation-config />peut faire, avec addition d'utiliser les stéréotypes par exemple .. @Component, @Service, @Repository. Vous pouvez donc câbler des beans entiers et pas seulement restreints aux constructeurs ou aux propriétés!.


31

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

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


@Autowired et @Required sont des propriétés de niveau cible, donc le bean doit s'enregistrer au printemps IOC avant d'utiliser ces annotations. Pour activer ces annotations, vous devez enregistrer les beans respectifs ou les inclure <context:annotation-config />. c'est à dire ne <context:annotation-config />fonctionne qu'avec des beans enregistrés.

@Required active l' RequiredAnnotationBeanPostProcessor outil de traitement
@Autowired active l' AutowiredAnnotationBeanPostProcessoroutil de traitement

Remarque: L' annotation elle-même n'a rien à faire, nous avons besoin d'un outil de traitement , qui est une classe en dessous, responsable du processus principal.


@Repository, @Service et @Controller sont @Component et ciblent le niveau de classe .

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

Migration de XML vers des annotations


15

La <context:annotation-config>balise 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, ceux-ci peuvent être enregistrés en tant que définitions de haricots individuels, mais ils peuvent également être implicitement enregistrés en incluant<context:annotation-config> balise dans la configuration du ressort.

Tiré de la documentation Spring de la configuration basée sur les annotations


Spring offre la capacité de détecter automatiquement les classes «stéréotypées» et d'enregistrer les BeanDefinitions 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 (à un niveau conceptuel plutôt que d'implémentation). Exemple: @Controller @Service @Repository etc. Ceux-ci sont destinés à être utilisés par des outils et des aspects (faisant une cible idéale pour les coupes de points).

Pour détecter automatiquement ces classes de «stéréotypes», une <context:component-scan>balise est requise.

La <context:component-scan>balise indique également à Spring d'analyser le code des beans injectables sous le package (et tous ses sous-packages) spécifié.


14
<context:annotation-config>

Ne résout que les annotations @Autowiredet @Qualifer, c'est tout, il s'agit de l' injection de dépendance , il y a d'autres annotations qui font le même travail, je pense comment@Inject , mais tout sur le point de résoudre DI via des annotations.

Attention, même lorsque vous avez déclaré l' <context:annotation-config>élément, vous devez quand même déclarer votre classe comment un Bean, rappelez-vous que nous avons trois options

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

Maintenant avec

<context:component-scan>

Cela fait deux choses:

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

Par conséquent, si vous déclarez <context:component-scan>, il n'est plus nécessaire de 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 beans, rien à propos de <constructor-arg>et <property>, la DI est configurée dans leurs propres classes via @Autowired. Cela signifie que les services utilisent @Autowired pour leurs composants de référentiels et que les référentiels utilisent @Autowired pour les composants JdbcTemplate, DataSource, etc.


1
superbe explication Merci. @Manuel Jordan
BALS

7
<context:component-scan /> implicitly enables <context:annotation-config/>

essayez avec <context:component-scan base-package="..." annotation-config="false"/>, dans votre configuration @Service, @Repository, @Component fonctionne très bien, mais @ Autowired, @ Resource et @Inject ne fonctionne pas.

Cela signifie que AutowiredAnnotationBeanPostProcessor ne sera pas activé et que le conteneur Spring ne traitera pas les annotations de câblage automatique.


Celui-ci m'a aidé à comprendre que <context: component-scan /> active implicitement <context: annotation-config />; c'est-à-dire qu'il analyse les définitions de bean ainsi que l'injection nécessaire. J'ai expérimenté avec annotation-config = "false", et l'injection n'a pas fonctionné sauf si j'ai explicitement défini en utilisant <context: annotation-config />. Enfin ma compréhension est meilleure qu'avant!
CuriousMind

5
<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'autre point important à noter est qu'il context:component-scanappelle implicitement le context:annotation-configpour activer les annotations sur les beans. Eh bien, si vous ne voulez context:component-scanpas activer implicitement les annotations pour vous, vous pouvez continuer à définir l'élément annotation-config du context:component-scanto false.

Résumer:

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

1

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

Ceci est utilisé pour indiquer au conteneur qu'il y a des classes de bean dans mon package qui analysent ces classes de bean. Afin d'analyser les classes de bean par conteneur au-dessus du bean, nous devons écrire l'une des annotations de type stéréo comme suit.

@Component, @Service, @Repository,@Controller

<context:annotation-config />:

Si nous ne voulons pas écrire explicitement la balise du bean en XML, alors comment le conteneur sait s'il y a un câblage automatique dans le bean. Cela est possible en utilisant l' @Autowiredannotation. nous devons informer le conteneur qu'il y a un câblage automatique dans mon haricot context:annotation-config.


0

Une <context:component-scan/>balise personnalisée enregistre le même ensemble de définitions de bean que celui utilisé par, en dehors de sa responsabilité principale d'analyser les packages java et d'enregistrer les définitions de bean à partir du chemin de classe.

Si, pour une raison quelconque, cet enregistrement des définitions de bean par défaut doit être évité, la manière de le faire consiste à spécifier un attribut supplémentaire "annotation-config" dans le composant-scan, de cette façon:

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

Référence: http://www.java-allandsundry.com/2012/12/contextcomponent-scan-contextannotation.html


0

<context:annotation-config>:

Cela indique à Spring que je vais utiliser des beans annotés comme Spring Bean et ceux-ci seront câblés via des @Autowiredannotations, au lieu de déclarer dans le fichier xml de config de Spring.

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

Cela indique au conteneur Spring où commencer la recherche de ces beans annotés. Ici, le printemps recherchera tous les sous-packages du package de base.


0

vous pouvez trouver plus d'informations dans le fichier de schéma de contexte de printemps. ce qui suit est dans 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

En complément, vous pouvez utiliser @ComponentScanpour utiliser <context:component-scan>de manière annotée.

Il est également décrit au printemps.io

Configure les directives d'analyse des composants à utiliser avec les classes @Configuration. Fournit une prise en charge parallèle à l'élément Spring XML.

Une chose à noter, si vous utilisez Spring Boot, la @Configuration et @ComponentScan peuvent être implicites en utilisant l'annotation @SpringBootApplication.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.