Guide to Spring @Autowired

Guide du printemps @Autowired

1. Vue d'ensemble

À partir de Spring 2.5, le framework a introduit un nouveau style d'injection de dépendances piloté par les annotations@Autowired. Cette annotation permet à Spring de résoudre et d’injecter des haricots collaborateurs dans votre haricot.

Dans ce tutoriel, nous verrons comment activer l'autowiring, diverses annotations ways to wire in beans,_ making beans optional, resolving bean conflicts using _@Qualifier ainsi que des scénarios d'exception potentiels.

Lectures complémentaires:

Balayage des composants Spring

En savoir plus sur le mécanisme à la base de l'analyse des composants Spring et sur la manière de l'adapter à vos propres besoins

Read more

Introduction à l'inversion du contrôle et injection de dépendance avec ressort

Une introduction rapide aux concepts d'inversion de contrôle et d'injection de dépendance, suivie d'une démonstration simple à l'aide du framework Spring

Read more

2. Activation des annotations@Autowired

Si vous utilisez une configuration basée sur Java dans votre application, vous pouvez activer l'injection basée sur les annotations en utilisantAnnotationConfigApplicationContext pour charger votre configuration de ressort comme ci-dessous:

@Configuration
@ComponentScan("com.example.autowire.sample")
public class AppConfig {}

Comme alternative, dans Spring XML, il peut être activé en le déclarant dans des fichiers XML Spring comme ceci:<context:annotation-config/>

3. Utilisation de@Autowired

Une fois l'injection d'annotation activée, le câblage automatique peut être utilisé sur les propriétés, les paramètres et les constructeurs.

3.1. @Autowired sur les propriétés

L'annotation peut être utilisée directement sur les propriétés, éliminant ainsi le besoin de getters et de setters:

@Component("fooFormatter")
public class FooFormatter {

    public String format() {
        return "foo";
    }
}
@Component
public class FooService {

    @Autowired
    private FooFormatter fooFormatter;

}

Dans l'exemple ci-dessus, Spring recherche et injectefooFormatter lorsqueFooService est créé.

3.2. @Autowired sur les Setters

L'annotation@Autowired peut être utilisée sur les méthodes setter. Dans l'exemple ci-dessous, lorsque l'annotation est utilisée sur la méthode setter, la méthode setter est appelée avec l'instance deFooFormatter lorsqueFooService est créé:

public class FooService {

    private FooFormatter fooFormatter;

    @Autowired
    public void setFooFormatter(FooFormatter fooFormatter) {
            this.fooFormatter = fooFormatter;
    }
}

3.3. @Autowired sur les constructeurs

L'annotation@Autowired peut également être utilisée sur les constructeurs. Dans l'exemple ci-dessous, lorsque l'annotation est utilisée sur un constructeur, une instance deFooFormatter est injectée comme argument au constructeur lorsqueFooService est créé:

public class FooService {

    private FooFormatter fooFormatter;

    @Autowired
    public FooService(FooFormatter fooFormatter) {
        this.fooFormatter = fooFormatter;
    }
}

4. Dépendances @Autowired et Optionnelles

Spring s'attend à ce que les dépendances de@Autowired soient disponibles lorsque le bean dépendant est en cours de construction. Si la structure ne peut pas résoudre un bean pour le câblage, elle lève l'exception ci-dessous et empêche le lancement du conteneur Spring:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type [com.autowire.sample.FooDAO] found for dependency:
expected at least 1 bean which qualifies as autowire candidate for this dependency.
Dependency annotations:
{@org.springframework.beans.factory.annotation.Autowired(required=true)}

Pour éviter cela, un bean peut éventuellement être spécifié comme suit:

public class FooService {

    @Autowired(required = false)
    private FooDAO dataAccessor;

}

5. Désambiguïsation automatique

Par défaut, Spring résout les entrées@Autowired par type. Si plusieurs conteneurs du même type sont disponibles dans le conteneur, la structure lève une exception fatale indiquant que plusieurs beans sont disponibles pour le câblage automatique.

5.1. Câblage automatique par@Qualifier

L'annotation@Qualifier peut être utilisée pour indiquer et affiner le bean requis:

@Component("fooFormatter")
public class FooFormatter implements Formatter {

    public String format() {
        return "foo";
    }
}
@Component("barFormatter")
public class BarFormatter implements Formatter {

    public String format() {
        return "bar";
    }
}
public class FooService {

    @Autowired
    private Formatter formatter;

}

Puisqu'il existe deux implémentations concrètes deFormatter disponibles pour le conteneur Spring à injecter, Spring lancera une exceptionNoUniqueBeanDefinitionException lors de la construction desFooService: __

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException:
No qualifying bean of type [com.autowire.sample.Formatter] is defined:
expected single matching bean but found 2: barFormatter,fooFormatter

Cela peut être évité en restreignant l'implémentation à l'aide d'une annotation@Qualifier:

public class FooService {

    @Autowired
    @Qualifier("fooFormatter")
    private Formatter formatter;

}

En spécifiant les@Qualifier avec le nom de l'implémentation spécifique, dans ce cas en tant quefooFormatter, nous pouvons éviter toute ambiguïté lorsque Spring trouve plusieurs beans du même type.

Veuillez noter que la valeur de l'annotation@Qualifier correspond au nom déclaré dans l'annotation@Component de notre implémentationFooFormatter.

5.2. Câblage automatique par qualificatif personnalisé

Spring nous permet de créer notre propre annotation@Qualifier. Pour créer un qualificatif personnalisé, définissez une annotation et fournissez l'annotation@Qualifier dans la définition comme ci-dessous:

@Qualifier
@Target({
  ElementType.FIELD, ElementType.METHOD, ElementType.TYPE, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface FormatterType {

    String value();

}

Une fois définis, lesFormatterType peuvent être utilisés dans diverses implémentations pour spécifier une valeur personnalisée:

@FormatterType("Foo")
@Component
public class FooFormatter implements Formatter {

    public String format() {
        return "foo";
    }
}
@FormatterType("Bar")
@Component
public class BarFormatter implements Formatter {

    public String format() {
        return "bar";
    }
}

Une fois les implémentations annotées, l'annotation de qualificateur personnalisé peut être utilisée comme suit:

@Component
public class FooService {

    @Autowired
    @FormatterType("Foo")
    private Formatter formatter;

}

La valeur spécifiée dans l'annotation@Target limite où le qualificatif peut être utilisé pour marquer les points d'injection.

Dans l'extrait de code ci-dessus, le qualificatif peut être utilisé pour lever l'ambiguïté du point où Spring peut injecter le bean dans un champ, une méthode, un type et un paramètre.

5.3. Câblage automatique par nom

Spring utilise le nom du bean comme valeur de qualificatif par défaut.

Donc, en définissant le nom de la propriété du bean, dans ce cas, commefooFormatter, Spring correspond à l'implémentation deFooFormatter et injecte cette implémentation spécifique lorsqueFooService est construit:

public class FooService {

    @Autowired
    private Formatter fooFormatter;

}

6. Conclusion

Bien que@Qualifier et la correspondance de secours du nom du bean puissent être utilisés pour se limiter à un bean spécifique, le câblage automatique est vraiment une question d'injection par type et c'est la meilleure façon d'utiliser cette fonctionnalité de conteneur.

Le code source de ce didacticiel se trouve dansthe GitHub project - il s'agit d'un projet basé sur Eclipse, il devrait donc être facile à importer et à exécuter tel quel.