Comme son nom l'indique, l'injection d'annotation est de réaliser l'injection par annotations. Les annotations courantes liées au ressort et à l'injection incluent Autowired, Resource, Qualifier, Service, Controller, Repository et Component.
Autowired est l'injection automatique, trouve automatiquement le haricot approprié du contexte du ressort à injecter
La ressource est utilisée pour spécifier l'injection de nom
Le qualificatif et la mise en ligne fonctionnent ensemble pour spécifier le nom du haricot
Le service, le contrôleur et le référentiel respectivement la classe en tant que classe de couche de service, classe de couche de contrôleur et classe de couche de stockage de données. Lorsque la configuration de l'annotation Spring Scan, ces classes seront marquées pour générer des haricots.
Le composant est un terme général. Les classes de marquage sont des composants. Lorsque les scans de ressort et la configuration d'annotations, ces classes seront marquées pour générer des haricots.
Le printemps prend en charge plusieurs méthodes d'annotation pour l'injection de dépendance des haricots:
@Resource Javax.annotation JSR250 (Annotations communes pour Java) @Inject Javax.inject JSR330 (injection de dépendance pour Java) @Autowired org.springframework.bean.factory Spring
Intuitivement, @Autowired est une annotation fournie par le printemps, et les autres sont des annotations intégrées par JDK lui-même, et Spring prend également en charge ces annotations. Mais quelle est la différence entre ces trois lorsqu'elle est utilisée? Après avoir testé la méthode, l'auteur a trouvé des fonctionnalités intéressantes.
La différence est résumée comme suit:
1. @Autowired a une propriété requise, qui peut être configurée comme fausse. Dans ce cas, si le haricot correspondant n'est pas trouvé, une exception ne sera pas jetée. @Inject et @Resource ne fournissent pas de configurations correspondantes, vous devez donc les trouver sinon une exception sera lancée.
2. @Autowired et @Inject sont fondamentalement les mêmes, car les deux utilisent AutowiredannotationBeanPostProcessor pour gérer l'injection de dépendance. Mais @Resource est une exception, qui utilise CommonannotationBeanPostProcessor pour gérer l'injection de dépendance. Bien sûr, les deux sont desprocesseurs BeanPost.
@Autowired et @Inject - par défaut Autowired by Type - Autowired by Qualifier le nom peut être explicitement spécifié via @qualifier. - Si automatiquement par type échoue (les implémentations non trouvées ou multiples sont trouvées), dégénère à Autowired par nom de champ @Resource - par défaut Autowired par nom de champ - Si le nom de champ automatique par le champ échoue, dégénéré à @qualifier - si le nom de qualification axé sur le nom de qualification par le nom de qualification, les dégénérats par le champ auto-alimenté par le champ. Mais pour le moment, si le nom de champ automatique par le champ échoue, il ne dégénérera plus en type automatique par type.
Conseils Nom qualifié vs Nom de haricot
Dans Spring Design, le nom qualifié n'est pas équivalent au nom de haricot, ce dernier doit être unique, mais le premier est similaire à la fonction d'une balise ou d'un groupe, classant des haricots spécifiques. Il peut réaliser l'effet de Getbytag (groupe). Pour les haricots configurés XML, vous pouvez spécifier le nom de bean via l'attribut ID (s'il n'est pas spécifié, le nom de classe est en minuscules par défaut), et le nom de qualification est spécifié via la balise:
<bean id = "Lamborghini"> <qualificatif value = "luxe" /> <! - Injectez toutes les dépendances requises par ce haricot -> </bEAN>
Si c'est par annotation, vous pouvez spécifier le nom de qualification via l'annotation @qualifier et spécifier le nom de bean via la valeur de @Named ou @Component (@Service, @Repository, etc.):
@Component ("Lamborghini") @qualifier ("luxe") classe publique Lamborghini implémente la voiture {}ou
@Component @Named ("Lamborghini") @qualifier ("luxe") classe publique Lamborghini implémente la voiture {}De même, si le nom de haricot n'est pas spécifié, Spring sera par défaut en minuscules dans le nom de la classe (Lamborghini => Lamborghini).
3. Utilisez la méthode de dépendance à l'injection d'anotation pour effectuer avant la méthode d'injection XML. Si deux méthodes d'injection sont utilisées en même temps sur la dépendance du même bean, le XML est préféré. Cependant, je ne suis pas inquiet que les dépendances injectées par l'anotation ne puissent pas injecter des haricots configurés dans XML. L'injection de dépendance est effectuée après l'enregistrement du haricot.
4. La méthode actuelle Autowired By Type (l'auteur utilise la version 3.2.3.Release), l'implémentation de Spring AutowiredannotationBeanPostProcessor a des "bogues", ce qui signifie que @Autowired et @Inject ont des pièges (appelés pits, pas bogues car ils semblent être intentionnels ...). Il s'agit d'un bug qui vient en ligne et est également la raison de la rédaction d'articles ici. La scène est la suivante:
Il existe les définitions suivantes dans Application-Context.xml:
<xml version = "1.0" encoding = "utf-8"?> <beans xmlns = "http://www.springframework.org/schema/beans" xmlns: xsi = "http://www.w3.org/2001/xmlschema-instance" xmlns: aop = "http://www.springframework.org/schema/aop" xmlns: context = "http://www.springframework.org/schema/context" xmlns: util = "http://www.springframeworkwork.org/schema" xsi: schemalocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/springframeworks-3.0.xsd http://www.springframework.org/schema/aoph http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/context/spring-context-3.0.xsdd http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.xsd "> <Context: Annotation-Config /> <Context: Component-Scan Base-Package = "me.arganzheng.study" /> <util: constant id = "en" static-field = "me.arganzheng.study.spring.autowired.constants.language.en" /> <util: Constant Id = "ja" static-field = "me.arganzheng.study.spring.autowired.constants.language.jp" /> <util: constant id = "Ind" static-field = "me.arganzheng.study.spring.autowired.constants.language.ind" /> <util: Constant Id = "pt" static-field = "me.arganzheng.study.spring.autowired.constants.language.pt" /> <util: constant id = "th" static-field = "me.arganzheng.study.spring.autowired.constants.language.th" /> <util: Constant Id = "ar" static-field = "me.arganzheng.study.spring.autowired.constants.language.ar" /> <util: constant id = "en-rin" static-field = "me.arganzheng.study.spring.autowired.constants.language.en_rin" /> <util: map id = "langangesmap" key-type = "java.lang.string" value-type = "java.lang.string"> <entrée key = "pt" value = "pt" /> <entrée key = "br" value = "pt" /> <entrée key = "jp" value = "ja" /> <entrée key = "ja" value = "ja" /> <henty key = "value" ind " key = "id" value = "Ind" /> <entrée key = "en-rin" value = "en-rin" /> <entrée key = "dans" value = "en-rin" /> <entry key = "en" value = "en" /> <entry key = "gb" value = "en" /> <entrée clé = "th" value = "th" /> <entry key = "ar" value = "ar" ar "/> <great key =" eg "eg" eg " </ util: map> </ beans>
Les constantes appliquées par le champ statique sont définies dans la classe suivante:
Package me.arganzheng.study.spring.autowired; Constantes d'interface publique {Langue d'interface publique {chaîne finale statique publique en = "CommonConstants.lang_english"; public statique final string jp = "CommonConstants.lang_japanais"; String final statique public Ind = "CommonConstants.lang_indonesian"; Public Static Final String PT = "CommonConstants.lang_portstugais"; chaîne finale statique publique th = "CommonConstants.lang_thai"; Public static final String en_rin = "CommonConstants.lang_english_india"; String final statique publique ar = "CommonConstants.lang_arabic"; }}Ensuite, si nous déclarons la dépendance dans le code comme suit:
classe publique AutowiredTest étend BasesPringTestCase {@Autowired Private Map <String, String> LanguageChangeSmap; @Test public void testAutowired () {notNull (LanguageChangeSmap); System.out.println (LanguageChangeSMap.getClass (). GetSIMPLename ()); System.out.println (LanguageChangeSmap); }}Devinez quoi, quelque chose de bizarre s'est produit!
Les résultats de l'opération sont les suivants:
LinkedHashmap {en = CommonConstants.lang_english, ja = CommonConstants.lang_japanais, Ind = CommonConstants.lang_indonesian, pt = CommonConstants.Lang_portUgais, Th = CommunConstants.Lang_thai, ar = CommunConstants.Lang_arabic, en-Rin = CommonConstants.Lang_english}C'est-à-dire, carte
Sérieux: exception attrapée tout en permettant à TestExecutionListener
[org.springframework.test.context.support.dependencyInjectionStexECUTURSListener@5c51ee0a] pour préparer l'instance de test [me.arganzheng.study.spring.autowired.autowiredTest@6e301e0] org.springframewe «me.arganzheng.study.spring.autowired.AutowiredTest»: l'injection de dépendances auto-souriciées a échoué; L'exception imbriquée est org.springframework.beans.factory.beancreationException: Impossible de s'autowire sur le terrain: privé java.util.map me.arganzheng.study.spring.autowired.AutowiredTest.LanguageChangeSmap; L'exception imbriquée est org.springframework.beans.factory.nosuchBeAndeFinitionException: aucun bean de qualification de type [java.lang.string] trouvé pour la dépendance [carte avec le type de valeur java.lang.string]: au moins 1 Bean qui se qualifie comme candidat automatique pour cette dépendance. Annotations de dépendance: {@ org.springframework.beans.factory.annotation.Autowired (requise = true)} ... ed par: org.springframework.beans.factory.nosuchBeandeFinitionException: Aucun bean de type qualificatif de type [Java.Lang.String] trouvé pour la dépendance avec une valeur avec une valeur de valeur Java.Lang. se qualifie comme candidat automatique pour cette dépendance. Annotations de dépendance: {@ org.springframework.beans.factory.annotation.Autowired (obligé = true)} sur org.springframework.beans.factory.support.defaultListableBeanfactory.raisenosuchBeandeFinIitionException (defaultListableBeanfactory.Java:986) à la org.springframework.beans.factory.support.defaultListableBeanFactory.Doresolvedependency (DefaultListableBeanFactory.java:843) sur org.springframework.beans.factory.support.defaultListableBeanfactory.Revedependency (DefaultListableBeanFactor org.springframework.beans.factory.annotation.AutowiredannotationBeanPostProcessor $ AutowiredFieldElement.inject (AutowiredannotationBeanPostProcessor.java:486) ... 28 autresJe l'ai débogué et j'ai découvert que c'était en effet un bug au printemps. Il y a un problème avec cette méthode dans DefaultListableBeanFactory:
Objet protégé DORESOLVEDEPENDENCE (DependencyDescriptor Descriptor, Class <?> Type, String Beanname, Set <string> AutowiredBaSaNaNaS, TypeConverter TypeConverter) lève BeanSexception {... else if (map.class.isassignablefrom (type) && type.isinterface ()) {class <? if (keytype == null ||! string.class.issignableFrom (keyType)) {if (descriptor.isrequired ()) {throw new FatalBeanException ("key type [" + keytype + "] de map [" + type.getname () + "] doit être affecté à [java.lang.string]");); } return null; } Class <?> ValueType = descriptor.getMapValuType (); if (valetype == null) {if (descriptor.isrequired ()) {lancez new fatalBeanException ("aucun type de valeur déclaré pour map [" + type.getName () + "]"); } return null; } Map <String, Object> MatchingBeans = FindAutowiRcandidates (beanname, valluetype, descripteur); if (MatchingBeans.Isempty ()) {if (Descriptor.IsRequired ()) {RaiseSoSuchBeAndeFinitionException (ValueType, "Map With Value Type" + ValuType.GetName (), Descriptor); } return null; } if (AutowiredBeAnNames! = null) {AutowiredBeanNames.Addall (MatchingBeans.KeySet ()); } return MatchBeans; } ...}La clé est cette phrase: carte
Sérieux: exception attrapée tout en permettant à TestExecutionListener
[org.springframework.test.context.support.dependencyInjectionTestexECUTURSListener@9476189] pour préparer l'instance de test [me.arganzheng.study.spring.autowired.autowiredtest@2d546e21] ... causée par: org.springframework.beans.factory.nosuchBeAndefinitionException: aucun bean de type de type [java.lang.string] trouvé pour la dépendance [carte avec le type de valeur java.lang.string]: attend au moins 1 bean qui se qualifie comme candidat automatique pour cette dépendance. Annotations de dépendance: {@ org.springframework.beans.factory.annotation.autowired (required = true), @ org.springframework.beans.factory.annotation.qualifier (value = LanguageChangeSmap)} at org.springframework.beans.factory.support.defaultListableBeanfactory.RaiseSuchBeAndeFinitionException (DefaultListableBeanFactory.java:986) org.springframework.beans.factory.support.defaultListableBeanFactory.Doresolvedependency (DefaultListableBeanFactory.java:843) sur org.springframework.beans.factory.support.defaultListableBeanfactory.Revedependency (DefaultListableBeanFactor org.springframework.beans.factory.annotation.AutowiredannotationBeanPostProcessor $ AutowiredFieldElement.inject (AutowiredannotationBeanPostProcessor.java:486) ... 28 autresAprès le débogage, j'ai constaté que le chemin d'exécution est le même que le nom Qualfie non spécifié. N'avez-vous pas précisé le nom de haricot? Pourquoi est-il encore automatiquement par type? Après un coup d'œil, j'ai découvert. La méthode Doresolvedependency de DefaultListableBeAnfactory fait la différence entre les types d'abord:
Objet protégé Doresolvedependency (DependencyDescriptor Descriptor, class <?> Type, string beanname, set <string> autowiredBamesNames, typeConverter TypeConverter) lève BeanSexception {object value = getAutowInSanDateresolver (). GetSuggeShedValue (Descriptor); if (value! = null) {if (valeur instanceof string) {String strVal = ResolveMedDedValue ((string) value); BeanDefinition bd = (beanname! = Null && contientbean (beanname)? GetMergedBeAnDefinition (beanname): null); Valeur = EvaluateBeAnDefinitionString (Strval, BD); } TypeConverter Converter = (TypeConverter! = Null? TypeConverter: getTypeConverter ()); return (descriptor.getField ()! = null? converter.Convertifnecesary (valeur, type, descriptor.getField ()): converter.Convertifnecessary (valeur, type, descriptor.getMethodParameter ())); } if (type.isArray ()) {class <?> ComponentType = type.getComponentType (); Map <string, object> correspondantBeans = findAutowiRcandidates (beanname, composantType, descripteur); if (MatchingBeans.IsempTy ()) {if (Descriptor.IsRequired ()) {RaiseNoSuchBeAndeFinitionException (ComponentType, "Array of" + ComponentType.GetName (), Descriptor); } return null; } if (AutowiredBeAnNames! = null) {AutowiredBeanNames.Addall (MatchingBeans.KeySet ()); } TypeConverter Converter = (TypeConverter! = Null? TypeConverter: getTypeConverter ()); return converter.Convertifnecessary (MatchingBeans.Values (), type); } else if (collection.class.isassignableFrom (type) && type.isinterface ()) {class <?> elementType = descriptor.getCollectionType (); if (elementType == null) {if (descriptor.isrequired ()) {lancer une nouvelle FatalBeanException ("aucun type d'élément déclaré pour la collection [" + type.getName () + "]"); } return null; } Map <String, Object> MatchingBeans = FindAutowiRcandidates (beanname, elementType, Descriptor); if (MatchingBeans.IsempTy ()) {if (Descriptor.IsRequired ()) {RaiseSoSuchBeAndeFinitionException (ElementType, "Collection de" + elementType.getName (), Descriptor); } return null; } if (AutowiredBeAnNames! = null) {AutowiredBeanNames.Addall (MatchingBeans.KeySet ()); } TypeConverter Converter = (TypeConverter! = Null? TypeConverter: getTypeConverter ()); return converter.Convertifnecessary (MatchingBeans.Values (), type); } else if (map.class.isassignableFrom (type) && type.isinterface ()) {class <?> keyType = descriptor.getMapKeyType (); if (keytype == null ||! string.class.issignableFrom (keyType)) {if (descriptor.isrequired ()) {throw new FatalBeanException ("key type [" + keytype + "] de map [" + type.getname () + "] doit être affecté à [java.lang.string]");); } return null; } Class <?> ValueType = descriptor.getMapValuType (); if (valetype == null) {if (descriptor.isrequired ()) {lancez new fatalBeanException ("aucun type de valeur déclaré pour map [" + type.getName () + "]"); } return null; } Map <String, Object> MatchingBeans = FindAutowiRcandidates (beanname, valluetype, descripteur); if (MatchingBeans.Isempty ()) {if (Descriptor.IsRequired ()) {RaiseSoSuchBeAndeFinitionException (ValueType, "Map With Value Type" + ValuType.GetName (), Descriptor); } return null; } if (AutowiredBeAnNames! = null) {AutowiredBeanNames.Addall (MatchingBeans.KeySet ()); } return MatchBeans; } else {map <string, object> correspondantBeans = findAutowiRcanDatedates (beanname, type, descripteur); if (MatchingBeans.Isempty ()) {if (Descriptor.IsRequired ()) {RaiseNoSuchBeAndeFinitionException (type, "", descripteur); } return null; } if (MatchingBeans.Size ()> 1) {String primaireBeAnName = déterminerPrimaryCanDate (MatchingBeans, Descriptor); if (primaireBeAnName == null) {lancer un nouveau NouniqueBeAnDefinitionException (Type, MatchingBeans.KeySet ()); } if (AutowiredBeAnNames! = null) {AutowiredBeanNames.add (primaireBeAnName); } return MatchingBeans.get (primaireBeAnName); } // Nous avons exactement un match. Map.entry <string, objet> entrée = correspond à l'entraine.EntrySet (). Iterator (). Next (); if (autowiredBeAnNames! = null) {autowiredBeAnNames.add (entrée.getKey ()); } return entry.getValue (); }}S'il s'agit d'un tableau, d'une collection ou d'une carte, automatiquement par type en fonction du type de l'élément de la classe de collection (le type de la carte utilise la valeur). Pourquoi est-ce si spécial? Il s'avère que le printemps est à cet effet: vous permettant d'injecter toutes les implémentations qui correspondent à la fois, c'est-à-dire que vous pouvez les injecter comme ceci:
@Autowired
Liste privée <CAR> voitures;
Si votre voiture a plusieurs implémentations, elle sera injectée et ne sera plus signalée
org.springframework.beans.factory.nosuchBeAndefinitionException: aucun bean unique de type [me.arganzheng.study.spring.autowired.car] est défini: le bean correspondant attendu mais trouvé 2: [Audi, Toyota].
Cependant, dans le cas ci-dessus, si vous utilisez @Resource, vous n'aurez pas ce problème:
classe publique AutowiredTest étend BasesPringTestCase {@Resource @qualifier ("LanguageChangeSmap") Carte privée <String, String> LanguageChangeSmap; @Test public void testAutowired () {ASSERTNOTNULL (LANGUAGECHANGESMAP); System.out.println (LanguageChangeSMap.getClass (). GetSIMPLename ()); System.out.println (LanguageChangeSmap); }}Fonctionnement normal:
LinkedHashmap {pt = pt, br = pt, jp = ja, ja = ja, ind = ind, id = ind, en-rin = en-rin, in = en-rin, en = en, gb = en, th = th, ar = ar, eg = ar} Bien sûr, si vous ne spécifiez pas @qualifier ("LanguageChangeSmap") et que le nom de champ n'est pas LanguageChangeSmap, la même erreur sera toujours signalée.
Causé par: org.springframework.beans.factory.nosuchBeAndefinitionException: aucun bean de qualification de type [java.lang.string] trouvé pour la dépendance [carte avec le type de valeur java.lang.string]: attend au moins 1 bean qui se qualifie comme candidat automatique pour cette dépendance. Annotations de dépendance: {@ javax.annotation.resource (sharableable = true, mappedName =, description =, name =, type = class java.lang.object, authenticationType = conteneur, lookup =)} at at org.springframework.beans.factory.support.defaultListableBeanfactory.RaiseSuchBeAndeFinitionException (DefaultListableBeanFactory.java:986) org.springframework.beans.factory.support.defaultListableBeanFactory.Doresolvedependency (DefaultListableBeanFactory.java:843) sur org.springframework.beans.factory.support.defaultListableBeanfactory.Revedependency (DefaultListableBeanFactor org.springframework.context.annotation.commonannotationBeanPostProcessor.AutowireResource (CommonannotationBeanPostProcessor.java:438) org.springframework.context.annotation.commonannotationBeanPostProcessor.getResource (CommonannotationBeanPostProcessor.Java:416) org.springframework.context.annotation.commonannotationBeanPostProcessor $ ResourceElement.getResourceToinject (CommonannotationBeanPostProcessor.Java:550) org.springframework.beans.factory.annotation.injectionMetadata $ injectEdElement.inject (injectionmetadata.java:150) à org.springframework.beans.factory.annotation.injectionMetadata.inject (injectionMetadata.java:87) à l'affaire org.springframework.context.annotation.commonannotationBeanPostProcessor.PostProcessPropertyValues (CommonannotationBeanPostProcessor.java:303) ... 26 plusDe plus, @Resource peut également implémenter la liste ci-dessus pour recevoir toutes les implémentations:
classe publique AutowiredTest étend BasesPringTestCase {@Resource @qualifier ("LanguageChangeSmap") Carte privée <String, String> LanguageChangeSmap; @Resource Private List <CAR> voitures; @Test public void testAutowired () {ASSERTNOTNULL (LANGUAGECHANGESMAP); System.out.println (LanguageChangeSMap.getClass (). GetSIMPLename ()); System.out.println (LanguageChangeSmap); Assertnotnull (voitures); System.out.println (cars.getClass (). GetImpLename ()); System.out.println (CARS); }}En fonctionnement correctement:
LinkedHashmap {pt = pt, br = pt, jp = ja, ja = ja, ind = ind, id = ind, en-rin = en-rin, in = en-rin, en = en, gb = en, th = th, ar = ar, eg = ar} arrayListlist [me.arganzheng.study.spring.autowired.audi@579584da, me.arganzheng.study.spring.autowired.toyota@19453122]
En effet, l'annotation @Resource utilise le processeur CommonannotationBeanPostProcessor, qui n'est pas le même auteur que AutowiredannotationBeanPostProcessor [/ Smile]. Je ne l'analyserai pas ici. Les étudiants intéressés peuvent lire le code et l'étudier vous-même.
La conclusion finale est la suivante :
1. @Autowired et @Inject
Autowired by type peut être explicitement spécifié par @qualifier (classe non collectionnelle. Remarque: Non Autowired par Nom de Bean!)
Si Autowired by Type échoue (non trouvé ou plusieurs implémentations sont trouvées), dégénère à Autowired par nom de champ (classe de non-collection)
2. @Resource
Autowed par défaut par nom de champ
Si le nom de champ automatique par le champ échoue, il se dégénérera en autowired par type
Autowired par le nom de qualification peut être explicitement spécifié via @qualifier
Si le nom de qualification automatique par le nom de qualification échoue, il dégénérera en automatique par nom de champ. Cependant, si le nom de champ automatique par le champ échoue, il ne dégénérera plus en type automatique par type. Le projet de test est enregistré sur GitHub. Il s'agit d'un projet Maven standard. Les étudiants intéressés peuvent le cloner localement pour exécuter le test.
Remplir
Un collègue a souligné qu'il y a une phrase dans le document officiel du printemps qui entre en conflit avec ma relation:
Cependant, bien que vous puissiez utiliser cette convention pour faire référence à des haricots spécifiques par leur nom, @Autowired est fondamentalement une injection basée sur le type avec des qualifications sémantiques en option. Cela signifie que les valeurs de qualification, même avec le rendement du nom de bean, ont toujours une sémantique rétrécie dans l'ensemble des correspondances de type; Ils n'expriment pas sémantiquement une référence à un ID de bean unique.
En d'autres termes, même si @Autowired est ajouté avec l'annotation @qualifier, il est en fait automatiquement par type. @Qualifier n'est qu'un qualificatif, juste une condition de filtre. J'ai suivi le code et j'ai découvert que c'était en effet le cas. Ce nom @qualifier conçu par Spring n'est pas équivalent au nom de haricot. Il est un peu similaire à une étiquette. Cependant, si cette balise est unique, l'effet est en fait équivalent au nom de bean. En termes de mise en œuvre, Spring First GetbyType, obtenez des candidats à la liste, puis filtrez-le en fonction du nom de qualification.
Définir une autre Lamborghini, ici est spécifié à l'aide de @qualifier:
Package me.arganzheng.study.spring.autowired; import org.springframework.beans.factory.annotation.qualifier; import org.springframework.sterereotype.Component; @Component @qualifier ("luxe") classe publique Lamborghini implémente la voiture {}Définissez un autre Rolls-Royce, ici il est délibérément spécifié avec @Named:
Package me.arganzheng.study.spring.autowired; import javax.inject.named; import org.springframework.sterereotype.Component; @Component @Named ("Luxury") Classe publique Rollsroyce implémente la voiture {} Testez la voiture de luxe avec une définition injectée:
Package me.arganzheng.study.spring.autowired; Importer Static Junit.Framework.Asersert.AssertNotNull; Importer java.util.list; import me.arganzheng.study.basespringtestcase; import org.junit.test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.qualifier; / ** * * @author zhengzhibin * * / classe publique AutowiredTest étend BasesPringStCase {@Autowired @qualifier ("luxe") Liste privée <CAR> luxurycars; @Test public void testAutowired () {Assertnotnull (luxurycars); System.out.println (LuxuryCars.getClass (). GetImpLename ()); System.out.println (Luxurycars); }}Les résultats de l'opération sont les suivants:
ArrayList [me.arganzheng.study.spring.autowired.lamborghini@66b875e1, me.arganzheng.study.spring.autowired.rollsroyce@58433b76]
Supplément: Modes de mise en ligne
Spring prend en charge quatre modes Autowire. Lorsque vous utilisez des méthodes de configuration XML, vous pouvez les spécifier via l'attribut automatique.
Non. (Par défaut) Pas de automatique. Les références de haricots doivent être définies via un élément REF. La modification du paramètre par défaut n'est pas recommandée pour les déploiements plus importants, car la spécification des collaborateurs donne explicitement le contrôle et la clarté. Dans une certaine mesure, il documente la structure d'un système. byname. Automatique par nom de propriété. Spring recherche un haricot avec le même nom que la propriété qui doit être automatisée. Par exemple, si une définition de bean est définie sur Autowire par son nom et qu'il contient une propriété maître (c'est-à-dire qu'elle a une méthode Setmaster (..)), Spring recherche une définition de bean nommée Master et l'utilise pour définir la propriété. ByType. Permet à une propriété d'être automatiquement si exactement un haricot du type de propriété existe dans le conteneur. S'il existe plusieurs, une exception fatale est lancée, ce qui indique que vous ne pouvez pas utiliser ByType automatique pour ce haricot. S'il n'y a pas de haricots assortis, rien ne se passe; la propriété n'est pas définie. constructeur. Analogue à ByType, mais s'appliquent aux arguments du constructeur. S'il n'y a pas exactement un bean du type d'argument du constructeur dans le conteneur, une erreur fatale est augmentée.
Si vous utilisez @Autowired, @Inject ou @Resource Annotations, ce sera un peu plus compliqué, et il y aura un processus de dégradation échoué et un qualificatif sera introduit. Mais le principe de base est le même.