Comment Spring se connecte-t-il automatiquement par nom lorsque plusieurs bean correspondants sont trouvés?

106

Supposons que j'ai des interfaces telles que celles-ci:

interface Country {}
class USA implements Country {}
class UK implements Country ()

Et cet extrait de configuration xml:

<bean class="USA"/>
<bean id="country" class="UK"/>
<bean id="main" class="Main"/>

Comment puis-je contrôler quelle dépendance est câblée automatiquement ci-dessous? J'aimerais le Royaume-Uni.

class Main {
    private Country country;
    @Autowired
    public void setCountry(Country country) {
        this.country = country;
    }
}

J'utilise Spring 3.0.3.RELEASE.

Maniganda Prakash
la source
Je pensais que j'ajouterais que j'obtenais un "No unique bean of type ..." dans un environnement (de test) et que cela fonctionnait bien dans mon environnement de développement. Je suis sûr que c'était une sorte de chemin de classe, mais il s'est avéré que si vous ajoutez le @Qualifier, cela fonctionnait bien.
markthegrea

Réponses:

113

Ceci est documenté dans la section 3.9.3 du manuel Spring 3.0:

Pour une correspondance de secours, le nom du bean est considéré comme une valeur de qualificatif par défaut.

En d'autres termes, le comportement par défaut est comme si vous aviez ajouté @Qualifier("country")à la méthode setter.

skaffman
la source
Quand vous dites "nom du bean", voulez-vous dire le nom du champ qui contiendra le bean? (c'est-à-dire dans ce cas country)
Fund Monica's Lawsuit
67

Vous pouvez utiliser l'annotation @Qualifier

D' ici

Affiner le câblage automatique basé sur les annotations avec des qualificatifs

Étant donné que le câblage automatique par type peut conduire à plusieurs candidats, il est souvent nécessaire d'avoir plus de contrôle sur le processus de sélection. Une façon d'y parvenir est d'utiliser l'annotation @Qualifier de Spring. Cela permet d'associer des valeurs de qualificatif à des arguments spécifiques, réduisant ainsi l'ensemble des correspondances de type afin qu'un bean spécifique soit choisi pour chaque argument. Dans le cas le plus simple, cela peut être une valeur descriptive simple:

class Main {
    private Country country;
    @Autowired
    @Qualifier("country")
    public void setCountry(Country country) {
        this.country = country;
    }
}

Cela utilisera le Royaume-Uni, ajoutera un identifiant au bean USA et l'utilisera si vous voulez les USA.

Paul Whelan
la source
12

Une autre façon d'obtenir le même résultat consiste à utiliser l'annotation @Value:

public class Main {
     private Country country;

     @Autowired
     public void setCountry(@Value("#{country}") Country country) {
          this.country = country;
     }
}

Dans ce cas, la "#{country}chaîne est une expression SpEL (Spring Expression Language) qui correspond à un bean nommé country.

Ricardo Veguilla
la source
cela peut-il être injecté en fonction de la propriété? Que se passe-t-il si les États-Unis ou le Royaume-Uni sont une sorte de paramètre provenant de l'URL et que je veux injecter 2 choses différentes en fonction de ce que le paramètre est?
Kalpesh Soni
6

Une autre solution avec la résolution par nom:

@Resource(name="country")

Il utilise le package javax.annotation , il n'est donc pas spécifique à Spring, mais Spring le prend en charge.

thème
la source
1
mais @Resourcene sera pas
Dirk Hoffmann