J'ai lu plus sur le principe d'inversion de contrôle et l'injection de dépendance en tant que mise en œuvre et je suis presque sûr de le comprendre.
Il semble essentiellement dire "ne déclarez pas les instanciations de vos membres de classe au sein de la classe". Plutôt que les instanciations doivent être transmises et attribuées via le constructeur; "injecté" dans la classe à partir d'une source extérieure.
Si c'est aussi simple, ce qui semble être le cas, pourquoi avons-nous besoin de frameworks comme spring ou guice qui implémentent cela avec des annotations? Suis-je en train de manquer quelque chose de fondamental ici? J'ai vraiment du mal à comprendre à quoi servent les cadres d'injection de dépendance.
Edit: À propos du doublon possible, je pense que ma question est plus unique car elle concerne les frameworks DI en général, pas seulement Spring. Spring n'est pas seulement un framework DI, il y a donc de nombreuses raisons pour lesquelles quelqu'un voudrait utiliser Spring sans lien avec DI.
Nous n'avons pas besoin des cadres. Il est tout à fait possible d'implémenter l'injection de dépendances manuellement, même pour un projet relativement important.
D'un autre côté, l'utilisation d'un framework le rend plus facile, notamment basé sur des annotations ou la détection automatique des dépendances, car il simplifie le processus: si je décide que j'ai besoin d'une nouvelle dépendance dans une classe, tout ce que j'ai à faire est d'ajouter au constructeur (ou déclarer un setter) et l'objet est injecté - je n'ai pas besoin de changer de code d'instanciation.
De plus, les frameworks contiennent souvent d'autres fonctionnalités utiles. Spring, par exemple, contient un cadre utile pour la programmation orientée aspect, y compris la démarcation déclarative des transactions (qui est extrêmement pratique) et une variété d'implémentations d'adaptateurs qui facilitent l'intégration de nombreuses bibliothèques tierces.
Pourquoi avons-nous besoin de DI (injection de dépendance)?
Le mécanisme DI sépare la production d'objets de la consommation d'objets. Les dépendances dont un objet a besoin sont livrées de manière transparente de l'extérieur. L'avantage du mécanisme est clair: vous pouvez à tout moment échanger des dépendances, par ex. en utilisant un objet nul à des fins de test.
Comment cela se fait-il?
Il existe plusieurs façons d'atteindre l'objectif:
Avons-nous besoin de frameworks DI?
Non pas du tout. Vous pouvez simplement passer toutes les instances à d'autres objets manuellement. Si vous avez une petite application, il n'est pas nécessaire d'avoir un récipient à ressort.
Mais d'un autre côté, les frameworks vous aident dans la gestion des objets:
Ils vous aident à câbler des relations d'objets complexes. Vous ne devez écrire aucun code passe-partout, pour générer des instances et les transmettre aux objets appropriés
Ils vous aident à contrôler quand un objet est créé: vous pouvez créer des instances lors du démarrage de l'application, mais dans certains cas, une création paresseuse - uniquement en cas de besoin - est meilleure
Ils vous aident à contrôler combien les instances sont créées: une par durée de vie d'application ou une par requête (au cas où vous faites de la programmation Web)
Si votre projet a une taille appropriée - si vous ressentez le besoin d'écrire moins de code passe-partout - il est tout à fait logique d'utiliser un cadre (DI-). Il y a plus d'avantages que d'inconvénients.
Avec le printemps, c'est surtout une question de commodité.
Si vous avez la classe TopLevel
qui est la classe construit MiddleLevel
qui construit la classe LowLevel
et que vous réalisez que vous avez besoin d'un nouveau paramètre constructeur sur LowLevel
, vous devez ajoutez-le également à TopLevel
, et à MiddleLevel
, simplement pour que, quand il est temps pour MiddleLevel
de construire un LowLevel
, la valeur soit disponible afin que il peut être transmis à son constructeur. Avec le printemps, vous ajoutez simplement une annotation.
De plus, avec spring, il est possible de définir les dépendances dans un fichier de configuration externe au lieu de xml, et cela vous donne censément la possibilité de générer un nouveau système avec un câblage entièrement différent "sans changer de code". (À mon humble avis, cela est complètement mal orienté, car la modification de xml n'est pas très différente de la modification de code, et en fait, le code a généralement une bien meilleure vérification des erreurs et vérification de type que xml.)
Une autre chose est que beaucoup de gens ont peur des constructeurs; ils ne les comprennent pas, ils ne les aiment pas, ils préfèrent ne pas les utiliser.
Il y a quelques années, j'ai écrit un programme pour surveiller les pages Web, les portlets Web et même certaines tables de base de données dans une entreprise pour laquelle je travaillais. Je voulais qu'il soit suffisamment flexible pour que l'utilisateur puisse spécifier quels moniteurs s'exécuteraient et avec quels paramètres (URL, connexions, critères de réussite, etc.). Je l'ai donc écrit pour lire à partir d'un fichier XML et utiliser Java réflexion pour instancier les classes spécifiées et utiliser des méthodes de définition pour définir les paramètres spécifiés.
Plus tard, j'ai découvert que le printemps fera la même chose pour vous, et bien plus encore.
Donc, dans mon cas, j'ai trouvé que
L'utilisation d'un framework d'injection de dépendances permet de rendre le programme flexible et de spécifier plus facilement comment il fonctionnera (dans des paramètres bien définis bien sûr).
L'utilisation d'un framework DI tiers vous évite d'avoir à réinventer la roue.