Spring @Autowired usage

218

Quels sont les avantages et les inconvénients de l'utilisation de @Autowired dans une classe qui sera câblée au printemps?

Juste pour clarifier, je parle spécifiquement de l' annotation @Autowired , pas du câblage automatique en XML.

Je ne le comprends probablement pas, mais pour moi, cela ressemble presque à un anti-modèle - vos classes commencent à prendre conscience qu'elles sont liées à un cadre DI, plutôt que d'être simplement des POJO. Je suis peut-être un glouton pour la punition, mais j'aime avoir la configuration XML externe pour les beans, et j'aime avoir des câblages explicites, donc je sais exactement ce qui est câblé où.

Andy White
la source
4
Je m'intéresse aussi à ce sujet - la configuration de votre application MVC via des annotations au lieu de XML semble conduire à beaucoup de recherches sur "quelle classe est mappée à cette URL?" "qui s'occupe de ça?". J'aime avoir une seule source de configuration
matt b
6
le terme "@Autowiring" semble induire en erreur ici. Comme vous pouvez également effectuer un câblage automatique avec une configuration XML, la question d'origine doit être reformulée comme "Avantages et inconvénients de l'utilisation des annotations Spring". La réponse fournie se concentre davantage sur les aspects du câblage automatique et moins sur les aspects de l'utilisation des annotations.
Neeme Praks
Copie
tkruse

Réponses:

253

Pendant longtemps, j'ai cru qu'il y avait une valeur à avoir une "configuration centralisée et déclarative" comme les fichiers xml que nous utilisions tous. Ensuite, j'ai réalisé que la plupart des éléments des fichiers n'étaient pas de configuration - ils n'ont jamais été modifiés n'importe où après le développement. Ensuite, j'ai réalisé que "centralisé" n'a de valeur que dans des systèmes assez petits - ce n'est que dans les petits systèmes que vous pourrez jamais bloquer un fichier de configuration dans son ensemble . Et quelle est vraiment la valeur de la compréhension du câblage dans son ensemble, lorsque les mêmes "câblages" sont pour la plupart dupliqués par des dépendances dans le code? Donc, la seule chose que j'ai gardée, ce sont les métadonnées (annotations), qui sont toujours en quelque sorte déclaratives. Ceux-ci ne changent jamais à l'exécution et ils ne les données de "configuration" que quelqu'un changera à la volée - donc je pense que les conserver dans le code est bien.

J'utilise autant que possible le câblage automatique complet. J'aime cela. Je ne reviendrai pas au printemps à l'ancienne à moins d'être menacé à bout portant. Mes raisons de préférer pleinement @Autowiredont changé au fil du temps.

À l'heure actuelle, je pense que la raison la plus importante de l'utilisation du câblage automatique est qu'il y a une abstraction de moins dans votre système à suivre. Le "nom du bean" a effectivement disparu. Il s'avère que le nom du bean n'existe qu'en raison de xml. Ainsi, une couche complète d'indirections abstraites (où vous câblez le nom du bean "foo" dans le "bar" du bean) a disparu. Maintenant, je connecte l'interface "Foo" directement dans mon bean, et l'implémentation est choisie par le profil d'exécution. Cela me permet de travailler avec du code lors du traçage des dépendances et des implémentations. Quand je vois une dépendance auto-câblée dans mon code, je peux simplement appuyer sur la touche "aller à l'implémentation" dans mon IDE et la liste des implémentations connues apparaît. Dans la plupart des cas, il n'y a qu'une seule implémentation et je suis directement dans la classe. Pouvez' quelle implémentation est utilisée (je prétends que le contraire est plus proche de la vérité avec le câblage xml - drôle comment votre perspective change!)

Vous pouvez maintenant dire que ce n'est qu'une couche très simple, mais chaque couche d'abstraction que nous ajoutons à nos systèmes augmente la complexité. Je ne pense vraiment pas que le xml ait jamais ajouté de valeur réelle à un système avec lequel j'ai travaillé.

La plupart des systèmes avec lesquels j'ai déjà travaillé n'ont qu'une seule configuration de l'environnement d'exécution de production. Il peut y avoir d'autres configurations pour le test et ainsi de suite.

Je dirais que le câblage automatique complet est le rubis sur rails du printemps: il embrasse la notion qu'il existe un modèle d'utilisation normal et commun que la plupart des cas d'utilisation suivent. Avec la configuration XML, vous autorisez de nombreuses utilisations de configuration cohérentes / incohérentes qui peuvent / peuvent ne pas être prévues. J'ai vu tellement de configuration xml passer par dessus bord avec des incohérences - est-ce qu'elle est refactorisée avec le code? Je ne pensais pas. Ces variations existent-elles pour une raison? Généralement non.

Nous utilisons à peine des qualificatifs dans notre configuration et avons trouvé d'autres moyens de résoudre ces situations. C'est un "désavantage" évident que nous rencontrons: nous avons légèrement changé la façon dont nous codons pour le rendre plus fluide avec le câblage automatique: un référentiel client n'implémente plus l' Repository<Customer>interface générique mais nous créons une interface CustomerRepositoryqui s'étend Repository<Customer>. Parfois, il y a aussi une ou deux astuces en matière de sous-classement. Mais cela nous pointe généralement vers une frappe plus forte, ce qui est presque toujours une meilleure solution.

Mais oui, vous êtes lié à un style particulier de DI que le printemps fait. Nous ne rendons même plus de paramètres publics pour les dépendances (vous pouvez donc affirmer que nous sommes +1 dans le département d'encapsulation / masquage des informations) Nous avons encore du XML dans notre système, mais le XML ne contient essentiellement que les anomalies. Le câblage automatique complet s'intègre parfaitement avec xml.

La seule chose dont nous avons besoin maintenant est que le @Component, @Autowiredet le reste soit inclus dans un JSR (comme le JSR-250 ), donc nous n'avons pas à nous lier au ressort. C'est ainsi que les choses se sont passées dans le passé (les choses me viennent java.util.concurrentà l'esprit), donc je ne serais pas entièrement surpris si cela se reproduisait.

krosenvold
la source
5
Le javax.annotation / javax.inject est pris en charge par Spring, vous n'avez donc pas besoin d'avoir la dépendance du code sur Spring.
Michael Wiles
26

Pour moi, voici ce que j'aime / n'aime pas dans le ressort et le câblage automatique.

Avantages:

  • Le câblage automatique élimine la configuration XML désagréable.
  • Des annotations beaucoup plus faciles à utiliser qui vous permettent d'injecter directement à l'aide de champs, de méthodes de définition ou de constructeurs. Vous permet également d'annoter et de «qualifier» vos grains injectés.

Les inconvénients:

  • L'utilisation du câblage automatique et des annotations vous rend dépendant des bibliothèques Spring où, comme pour la configuration XML, vous pouvez choisir de l'exécuter avec ou sans Spring. Comme vous l'avez dit, vous devenez lié à un cadre DI.
  • En même temps, j'aime pouvoir «qualifier» les beans, pour moi, cela rend le code vraiment désordonné. Si vous devez injecter le même bean à plusieurs endroits, j'ai vu le même nom de chaîne répété partout. Pour moi, cela semble avoir le potentiel d'erreurs.

J'ai commencé à utiliser le câblage automatique presque exclusivement au travail, car nous dépendons tellement de l'intégration de Spring que le problème de dépendance est sans objet. J'ai travaillé sur un projet Spring MVC qui utilisait beaucoup le câblage automatique et était un peu difficile à comprendre.

Je pense que le câblage automatique est un goût acquis, une fois que vous vous y êtes habitué, vous réalisez à quel point il est puissant, facile et beaucoup moins mal à la tête que de travailler avec la configuration XML.

Jared Knipp
la source
3
la configuration xml devient beaucoup moins désagréable si vous utilisez la suite d'outils Springsource gratuite, qui comprend la saisie semi-automatique, les graphiques de bean, etc.
Sean Patrick Floyd
Je suis totalement d'accord avec vous sur le fait que le câblage automatique devient désordonné et dépend des bibliothèques de ressorts! Je n'ai jamais utilisé la configuration XML et je pense que je devrais peut-être emprunter cette voie?
James111
15

Nous passons de @Autowire à la configuration XML dans notre grand projet. Le problème réside dans les performances d'amorçage très faibles. Le scanner de câblage automatique charge toutes les classes à partir du chemin de classe de recherche de câblage automatique, de sorte que de nombreuses classes sont chargées avec impatience lors de l'initialisation de Spring.

Masterhard
la source
1
J'ai trouvé que javaconfig pourrait même être une meilleure solution pour démarrer des contextes partiels, ce qui est une grande victoire Mais vous pouvez les combiner assez facilement en utilisant @ Autowired / @ Inject sur les constructeurs (en d'autres termes, passez à l'injection de constructeur).
krosenvold
6

Il y a eu très peu de discussions sur la commutation des environnements. La plupart des projets sur lesquels j'ai travaillé étaient un vrai problème pour injecter des dépendances en fonction de l'environnement sur lequel nous travaillons. Avec la configuration xml, c'est assez simple avec Spring EL, et je ne connais aucune bonne solution avec des annotations. Je viens d'en découvrir un:

    @Value("#{${env} == "production" ? realService : dummyService}")
    private SomeService service;

Cela devrait fonctionner, mais pas une bonne solution à mon humble avis.

BTakacs
la source
J'ai ouvert un fil séparé à ce sujet, et il existe une solution avec Spring @Profileset @Configuration: blog.springsource.org/2011/02/14/… Voir aussi l'autre fil: stackoverflow.com/questions/13490393/…
BTakacs
4

Je suis passé à @Autowire. Maintenir la configuration XML sur autre chose qu'un petit projet est devenu une tâche à part entière et la compréhension s'est rapidement dégradée.

IntelliJ fournit un bon support (pas parfait) pour les annotations Spring.

Paul McKenzie
la source
3

Mon point de vue sur ce sujet est que la configuration xml réduit la clarté du code, en particulier dans les grands systèmes.

Des annotations comme @Component aggravent les choses. Il aide les développeurs à rendre les objets mutables, car les dépendances ne peuvent plus être définitives, étant donné que les constructeurs par défaut doivent être fournis. Les dépendances doivent être injectées via le setter public ou non contrôlées via @Autowired. [encore pire l'injection de dépendances est compromise avec des classes qui instancient leurs dépendances, je le vois toujours dans du code nouvellement écrit!]. Par non contrôlé, je veux dire, dans les grands systèmes, lorsque plusieurs implémentations (ou enfants) du type sont disponibles, il est beaucoup plus difficile de comprendre laquelle des implémentations était @Autowired, une complexité qui rend l'enquête sur les bogues beaucoup plus difficile. Cela signifie également que, soi-disant, vous avez un profil pour l'environnement de test et un autre pour la production,

Je m'en tiens au milieu où je déclare ma (mes) classe (s) de configuration (configuration Spring basée sur java en utilisant @Configuration)

Je déclare explicitement tous mes beans dans la ou les classes de configuration. J'utilise uniquement @Autowired dans les classes de configuration, le but est de limiter la dépendance de Spring aux classes de configuration

La @Configuration réside dans un package spécifique, c'est le seul endroit où l'analyse de printemps s'exécute. (Cela accélère considérablement le démarrage dans les grands projets)

Je m'efforce de rendre toutes mes classes immuables, en particulier l'objet de données, JPA, Hibernate et Spring, ainsi que de nombreuses bibliothèques de sérialisation semblent miner cela. Je m'éloigne de tout ce qui m'oblige à fournir des setters, ou je retire le mot-clé final de ma déclaration de propriété.

Réduire les possibilités de changer des objets après leur création, réduit considérablement les bogues dans les grands systèmes ainsi que le temps de trouver un bogue lorsqu'il existe.

Il semble également que cela oblige le développeur à mieux concevoir l'interaction entre les différentes parties du système. Les problèmes et les bogues deviennent de plus en plus d'erreurs de compilation, ce qui réduit le temps perdu et améliore la productivité.

Charbel
la source
1

Voici quelques - unes d'expérience
Pros

  • Facilite la configuration car nous pouvons simplement utiliser l'annotation @Autowire
  • Je ne veux pas utiliser de méthodes de définition, donc la classe sera plus propre

Les inconvénients

  • Couple étroitement au fichier xml même si nous utilisons DI
  • Mise en œuvre difficile à trouver (mais si vous utilisez de bons ides comme intellij, vous pouvez vous en débarrasser)

À partir de mes expériences personnelles, je n'ai pas beaucoup utilisé l'annotation @AutoWire, mais dans les cas de test.

Rajith Delantha
la source
1

J'adore vraiment écrire avec des annotations, au lieu de XML. Selon le manuel Spring et les dernières versions, XML et Annotation ont obtenu le même résultat.

C'est ma liste

Pro:

  • Supprimer la ligne inutile de xml
  • Simplifiez le débogage du code: lorsque vous ouvrez une classe, vous pouvez lire ce que vous avez dans la classe
  • Développement plus rapide, un projet avec 400 lignes XML ou plus est lisible?

Les inconvénients:

  • N'est pas une implémentation Java standard, mais vous pouvez passer à l'utilisation de @Inject, qui est une API Java Standard, de sorte que le bean reste un Pojo
  • Vous ne pouvez pas simplement utiliser partout, connexion db et ainsi de suite, mais ce n'est qu'une opinion, je préfère avoir un endroit où lire toute la configuration.
Luca Preziati
la source
0

Pour ma compréhension, @Autowired est le meilleur à utiliser tout en se référant à la référence d'interface et en utilisant ses fonctions de remplacement, mais je trouve que le problème est qu'il est parfois attribué à null lors de l'exécution.

Shubham kapoor
la source