TL; DR
L'annotation @Autowired vous épargne le besoin de faire le câblage par vous-même dans le fichier XML (ou de toute autre manière) et trouve juste pour vous ce qui doit être injecté où, et le fait pour vous.
Explication complète
L' @Autowired
annotation vous permet d'ignorer les configurations ailleurs de quoi injecter et le fait juste pour vous. En supposant que votre package est que com.mycompany.movies
vous devez mettre cette balise dans votre XML (fichier de contexte d'application):
<context:component-scan base-package="com.mycompany.movies" />
Cette balise effectuera une analyse automatique. En supposant que chaque classe qui doit devenir un bean est annotée avec une annotation correcte comme @Component
(pour le bean simple) ou @Controller
(pour un contrôle de servlet) ou @Repository
(pour les DAO
classes) et ces classes sont quelque part sous le package com.mycompany.movies
, Spring les trouvera toutes et créera un haricot pour chacun. Cela se fait en 2 scans des classes - la première fois, il recherche juste les classes qui doivent devenir un bean et mappe les injections qu'il doit faire, et lors du deuxième scan il injecte les beans. Bien sûr, vous pouvez définir vos beans dans le fichier XML plus traditionnel ou avec une classe @Configuration (ou une combinaison des trois).
L' @Autowired
annotation indique à Spring où une injection doit avoir lieu. Si vous le placez sur une méthode, setMovieFinder
il comprend (par le préfixe set
+ l' @Autowired
annotation) qu'un bean doit être injecté. Dans la deuxième analyse, Spring recherche un bean de type MovieFinder
et s'il trouve un tel bean, il l'injecte à cette méthode. S'il trouve deux de ces beans, vous obtiendrez un Exception
. Pour éviter cela Exception
, vous pouvez utiliser l' @Qualifier
annotation et lui indiquer lequel des deux beans injecter de la manière suivante:
@Qualifier("redBean")
class Red implements Color {
// Class code here
}
@Qualifier("blueBean")
class Blue implements Color {
// Class code here
}
Ou si vous préférez déclarer les beans dans votre XML, cela ressemblerait à ceci:
<bean id="redBean" class="com.mycompany.movies.Red"/>
<bean id="blueBean" class="com.mycompany.movies.Blue"/>
Dans la @Autowired
déclaration, vous devez également ajouter le @Qualifier
pour indiquer lequel des deux grains de couleur injecter:
@Autowired
@Qualifier("redBean")
public void setColor(Color color) {
this.color = color;
}
Si vous ne souhaitez pas utiliser deux annotations (le @Autowired
et @Qualifier
), vous pouvez utiliser @Resource
pour combiner ces deux:
@Resource(name="redBean")
public void setColor(Color color) {
this.color = color;
}
Le @Resource
(vous pouvez lire quelques données supplémentaires à ce sujet dans le premier commentaire sur cette réponse) vous épargne l'utilisation de deux annotations et à la place vous n'en utilisez qu'une.
Je vais juste ajouter deux autres commentaires:
- La bonne pratique serait d'utiliser à la
@Inject
place de @Autowired
car il n'est pas spécifique à Spring et fait partie de la JSR-330
norme .
- Une autre bonne pratique serait de mettre le
@Inject
/ @Autowired
sur un constructeur au lieu d'une méthode. Si vous le placez sur un constructeur, vous pouvez valider que les beans injectés ne sont pas nuls et échouent rapidement lorsque vous essayez de démarrer l'application et en éviter un NullPointerException
lorsque vous devez réellement utiliser le bean.
Mise à jour : Pour compléter l'image, j'ai créé une nouvelle question sur la @Configuration
classe.
MovieFinder
s'agit d'une interface et que nous avons un bean pourMovieFinderImpl
(bean id = movieFinder), Spring l'injectera automatiquement par type ou par nom?@Qualifier
. Si vous le faites - par nom, sinon - par type. Par type ne fonctionnerait que si vous n'avez qu'un seul bean de typeMovieFinder
dans votre contexte. Plus de 1 entraînerait une exception.@Autowired
annotation fonctionne sur laprepare
méthode de l' exemple 2 . Il initialise leMovieRecommender
mais, techniquement, ce n'est PAS un passeur.@Autowired
fonctionne également pour les constructeurs. Il trouve les dépendances requises et les injecte au constructeur.Rien dans l'exemple ne dit que les "classes implémentant la même interface".
MovieCatalog
est un type etCustomerPreferenceDao
est un autre type. Le printemps peut facilement les distinguer.Au printemps 2.x, le câblage des beans se faisait principalement via des ID ou des noms de beans. Ceci est toujours pris en charge par Spring 3.x mais souvent, vous aurez une instance d'un bean avec un certain type - la plupart des services sont des singletons. Créer des noms pour ceux-là est fastidieux. Spring a donc commencé à prendre en charge "autowire by type".
Les exemples montrent différentes manières que vous pouvez utiliser pour injecter des beans dans des champs, des méthodes et des constructeurs.
Le XML contient déjà toutes les informations dont Spring a besoin, car vous devez spécifier le nom de classe complet dans chaque bean. Vous devez cependant être un peu prudent avec les interfaces:
Ce câblage automatique échouera:
Comme Java ne conserve pas les noms des paramètres dans le code d'octet, Spring ne peut plus distinguer les deux beans. Le correctif consiste à utiliser
@Qualifier
:la source
prepare
, quels paramètres seront utilisés pour appeler cette fonction?@Autowired
champs sont injectés. Spring verra alors que les paramètres sont nécessaires et il utilisera les mêmes règles que celles utilisées pour l'injection sur le terrain pour trouver les paramètres.Oui, vous pouvez configurer le fichier xml de contexte de servlet Spring pour définir vos beans (c'est-à-dire, les classes), afin qu'il puisse effectuer l'injection automatique pour vous. Cependant, notez que vous devez effectuer d'autres configurations pour que Spring soit opérationnel et la meilleure façon de le faire est de suivre un tutoriel à la base.
Une fois que vous avez probablement configuré votre Spring, vous pouvez faire ce qui suit dans votre fichier xml de contexte de servlet Spring pour que l'exemple 1 ci-dessus fonctionne (veuillez remplacer le nom de package de com.movies par le vrai nom de package et s'il s'agit d'une tierce partie , assurez-vous que le fichier jar approprié se trouve sur le chemin d'accès aux classes):
ou si la classe MovieFinder a un constructeur avec une valeur primitive, alors vous pourriez quelque chose comme ça,
ou si la classe MovieFinder a un constructeur qui attend une autre classe, alors vous pouvez faire quelque chose comme ça,
... où ' otherBeanRef ' est un autre bean qui a une référence à la classe attendue.
la source
@Autowired