Qu'est-ce que l'injection de dépendance et l'inversion de contrôle dans Spring Framework?


112

«L'injection de dépendances» et «l'inversion de contrôle» sont souvent mentionnées comme les principaux avantages de l'utilisation du framework Spring pour le développement de frameworks Web

Quelqu'un pourrait-il expliquer ce que c'est en termes très simples avec un exemple si possible?



3
@SteveChambers ce n'est pas en double, cette question est posée dans Springs Perspective. Cette question est en général de préséance.
VdeX

Réponses:


233
  • Spring aide à la création d'applications faiblement couplées en raison de l' injection de dépendances .
  • Dans Spring, les objets définissent leurs associations (dépendances) et ne se soucient pas de la façon dont ils obtiendront ces dépendances . Il est de la responsabilité de Spring de fournir les dépendances requises pour la création d'objets.

Par exemple : Supposons que nous ayons un objet Employeeet qu'il ait une dépendance sur l'objet Address. Nous définirions un bean correspondant à Employeecelui qui définira sa dépendance à l'objet Address.

Lorsque Spring essaie de créer un Employeeobjet, il voit qu'il y Employeea une dépendance sur Address, donc il crée d'abord l' Addressobjet (objet dépendant), puis l'injecte dans l' Employeeobjet.

  • L'inversion de contrôle ( IoC ) et l'injection de dépendance ( DI ) sont utilisées de manière interchangeable. L'IoC est réalisé par DI. DI est le processus de fourniture des dépendances et IoC est le résultat final de DI. ( Remarque: DI n'est pas le seul moyen d'atteindre l'IoC. Il existe également d' autres moyens .)

  • Par DI, la responsabilité de créer des objets est transférée de notre code d'application au conteneur Spring; ce phénomène s'appelle IoC.

  • L'injection de dépendance peut être effectuée par injection de setter ou injection de constructeur.

Je ne suis pas d'accord. je ne pense pas que ce soit une explication claire. Pourquoi ne pouvez-vous pas simplement instancier "Address" dans "Employee" au lieu d'obtenir un framework pour le créer et l'injecter? Un exemple un peu plus détaillé s'impose.
Boris

2
@Boris Personne n'a dit que vous ne pouviez pas instancier vos propres objets. Mais le seul objectif de la réponse était de démontrer comment vous pouvez obtenir la même chose avec DI. Vous pouvez avoir à la fois DI et des objets instanciés par code client. Cela s'appellerait encore IOC, au moins partiellement.
bogdan.rusu


Boris. Trop jaloux? C'est la meilleure réponse qui soit.
Aniket Kapse

31

Je vais écrire ma compréhension simple de ces deux termes: (Pour une compréhension rapide, lisez simplement des exemples)

  • Injection de dépendances (DI): L'
    injection de dépendances signifie généralement passer un objet dépendant en tant que paramètre à une méthode, plutôt que de laisser la méthode créer l'objet dépendant .
    Ce que cela signifie en pratique, c'est que la méthode n'a pas de dépendance directe sur une implémentation particulière; toute implémentation qui répond aux exigences peut être passée en paramètre.

    Avec cette implémentation des objets définit leurs dépendances. Et le printemps le rend disponible.
    Cela conduit à un développement d'applications faiblement couplé.

    Exemple rapide: OBJET EMPLOYÉ UNE FOIS CRÉÉ, IL CRÉERA AUTOMATIQUEMENT UN OBJET ADRESSE (si l'adresse est définie comme dépendance par l'objet Employé) *.

  • Conteneur d'inversion de contrôle (IoC):
    C'est une caractéristique commune des frameworks, IoC gère les objets Java
    - de l'instanciation à la destruction via son BeanFactory.
    - Les composants Java instanciés par le conteneur IoC sont appelés beans, et le conteneur IoC gère la portée d'un bean, les événements du cycle de vie et toutes les fonctionnalités AOP pour lesquelles il a été configuré et codé.

    QUICK EXAMPLE:Inversion of Control is about getting freedom, more flexibility, and less dependency. When you are using a desktop computer, you are slaved (or say, controlled). You have to sit before a screen and look at it. Using keyboard to type and using mouse to navigate. And a bad written software can slave you even more. If you replaced your desktop with a laptop, then you somewhat inverted control. You can easily take it and move around. So now you can control where you are with your computer, instead of computer controlling it.

    En implémentant l'inversion de contrôle, un consommateur de logiciel / objet obtient plus de contrôles / options sur le logiciel / objets, au lieu d'être contrôlé ou d'avoir moins d'options.

    L'inversion du contrôle en tant que directive de conception sert les objectifs suivants:
    - Il y a un découplage entre l'exécution d'une certaine tâche et la mise en œuvre.
    - Chaque module peut se concentrer sur ce pour quoi il est conçu.
    - Les modules ne font aucune hypothèse sur ce que font les autres systèmes mais s'appuient sur leurs contrats.
    - Le remplacement des modules n'a aucun effet secondaire sur les autres modules

Je vais garder les choses abstraites ici, vous pouvez visiter les liens suivants pour une compréhension détaillée du sujet.

Une bonne lecture avec exemple

Explication détaillée


11

Dans Spring, les objets sont faiblement couplés, c'est-à-dire que chaque classe est indépendante l'une de l'autre de sorte que tout peut être testé individuellement. Mais lors de l'utilisation de ces classes, une classe peut dépendre d'autres classes qui doivent d'abord être instanciées.

Donc, nous disons à spring que la classe A dépend de la classe B.Ainsi, lors de la création d'un bean (comme la classe) pour la classe A, il instancie la classe B avant celle de la classe A et l'injecte dans la classe A en utilisant des méthodes DI setter ou constructeur. C'est-à-dire que nous disons au printemps la dépendance au moment de l'exécution. C'est DI.

Comme nous attribuons la responsabilité de créer des objets (beans), de les maintenir et de leurs agrégations à Spring au lieu de les coder en dur, nous l'appelons Inversion Of Control (IOC).


7

Inversion de contrôle (IOC):

IoC est un modèle de conception qui décrit l'inversion du flux de contrôle dans un système, de sorte que le flux d'exécution n'est pas contrôlé par un élément de code central. Cela signifie que les composants ne doivent dépendre que des abstractions d'autres composants et ne sont pas responsables de la gestion de la création des objets dépendants. Au lieu de cela, les instances d'objet sont fournies au moment de l'exécution par un conteneur IoC via l'injection de dépendances (DI).

L'IoC permet une meilleure conception logicielle qui facilite la réutilisation, le couplage lâche et les tests faciles des composants logiciels.

Injection de dépendance (DI):

DI est une technique pour passer des dépendances dans le constructeur d'un objet. Si l'objet a été chargé à partir du conteneur, ses dépendances seront automatiquement fournies par le conteneur. Cela vous permet de consommer une dépendance sans avoir à créer manuellement une instance. Cela réduit le couplage et vous donne un meilleur contrôle sur la durée de vie des instances d'objet.

cliquez pour voir plus


6

Spring: Spring est le conteneur «Inversion of Control» pour la plateforme Java.

Inversion de contrôle (IoC): L'inversion de contrôle (IoC) est une pratique de programmation orientée objet dans laquelle le couplage d'objet est limité au moment de l'exécution par un objet «assembleur» et n'est généralement pas connaissable au moment de la compilation à l'aide de l'analyse statique.

Injection de dépendances (DI): "L'injection de dépendances est un modèle de conception logicielle qui permet la suppression des dépendances codées en dur et permet de les modifier, que ce soit au moment de l'exécution ou de la compilation." -wiki.


En quoi est-ce plus simple que ce qui existe déjà (d'où provient cette réponse)? Cela ne tient pas compte de la demande de simplicité du PO, à moins que les doubles guillemets autour des terminologies ne rendent les choses plus simples par magie.
Flame of udun

6

Inversion de contrôle - Cela signifie donner le contrôle de la création et de l'instanciation des beans spring dans le conteneur Spring IOC et le seul travail du développeur est de configurer les beans dans le fichier xml spring.

Injection de dépendance

Considérez un employé de classe

class Employee { 
   private int id;
   private String name;
   private Address address;

   Employee() {
     id = 10;
     name="name";
     address = new Address();
   }


}

et considérez l'adresse de classe

class Address {
   private String street;
   private String city;

   Address() {
     street="test";
     city="test1";

  }
}

Dans le code ci-dessus, les valeurs de classe d'adresse ne seront définies que lorsque la classe Employee est instanciée, qui est la dépendance de la classe Address sur la classe Employee. Et spring résout ce problème en utilisant le concept d'injection de dépendance en fournissant deux façons d'injecter cette dépendance.

  1. Injection de poseur

Méthode Setter dans la classe Employee qui prend une référence de la classe Address

public void setAddress(Address addr) {
    this.address = addr;
}
  1. Injection de constructeur

Constructeur dans la classe Employee qui accepte Address

Employee(Address addr) {
      this.address = addr;
}

De cette manière, les valeurs de la classe Address peuvent être définies indépendamment à l'aide de l'injection setter / constructeur.


3

L'inversion de contrôle est un principe de conception générique de l'architecture logicielle qui aide à créer des cadres logiciels modulaires réutilisables et faciles à entretenir.

C'est un principe de conception dans lequel le flux de contrôle est "reçu" de la bibliothèque générique ou du code réutilisable.

Pour mieux le comprendre, voyons comment nous avions l'habitude de coder dans nos premiers jours de codage. Dans les langages procéduraux / traditionnels, la logique métier contrôle généralement le flux de l'application et «appelle» le code / les fonctions génériques ou réutilisables. Par exemple, dans une application console simple, mon flux de contrôle est contrôlé par les instructions de mon programme, qui peuvent inclure les appels à certaines fonctions générales réutilisables.

print ("Please enter your name:");
scan (&name);
print ("Please enter your DOB:");
scan (&dob);

//More print and scan statements
<Do Something Interesting>

//Call a Library function to find the age (common code)
print Age

En contraste, avec IoC, les Frameworks sont le code réutilisable qui «appelle» la logique métier.

Par exemple, dans un système basé sur Windows, un cadre sera déjà disponible pour créer des éléments d'interface utilisateur tels que des boutons, des menus, des fenêtres et des boîtes de dialogue. Lorsque j'écris la logique métier de mon application, ce sont les événements du framework qui appelleront mon code de logique métier (lorsqu'un événement est déclenché) et PAS l'inverse.

Bien que le code du framework ne connaisse pas ma logique métier, il saura toujours comment appeler mon code. Ceci est réalisé en utilisant des événements / délégués, des rappels, etc. Ici, le contrôle du flux est "inversé".

Ainsi, au lieu de dépendre du flux de contrôle sur des objets liés statiquement, le flux dépend du graphe d'objets global et des relations entre les différents objets.

L'injection de dépendances est un modèle de conception qui implémente le principe IoC pour résoudre les dépendances d'objets.

En termes plus simples, lorsque vous essayez d'écrire du code, vous créez et utilisez différentes classes. Une classe (classe A) peut utiliser d'autres classes (classe B et / ou D). Ainsi, les classes B et D sont des dépendances de la classe A.

Une simple analogie sera une voiture de classe. Une voiture peut dépendre d'autres classes comme le moteur, les pneus et plus encore.

L'injection de dépendances suggère qu'au lieu que les classes dépendantes (Class Car ici) créent ses dépendances (Class Engine et class Tire), la classe devrait être injectée avec l'instance concrète de la dépendance.

Permet de comprendre avec un exemple plus pratique. Considérez que vous écrivez votre propre TextEditor. Entre autres choses, vous pouvez avoir un correcteur orthographique qui offre à l'utilisateur la possibilité de vérifier les fautes de frappe dans son texte. Une implémentation simple d'un tel code peut être:

Class TextEditor
{

    //Lot of rocket science to create the Editor goes here

    EnglishSpellChecker objSpellCheck;
    String text;

    public void TextEditor()

    {   

        objSpellCheck = new EnglishSpellChecker();

    }

    public ArrayList <typos> CheckSpellings()
    {

        //return Typos;

    }

}

À première vue, tout semble rose. L'utilisateur écrira du texte. Le développeur capturera le texte et appellera la fonction CheckSpellings et trouvera une liste de fautes de frappe qu'il montrera à l'utilisateur.

Tout semble bien fonctionner jusqu'au jour où un utilisateur commence à écrire le français dans l'éditeur.

Pour fournir la prise en charge de plusieurs langues, nous avons besoin de plus de vérificateurs d'orthographe. Probablement français, allemand, espagnol, etc.

Ici, nous avons créé un code étroitement couplé avec SpellChecker "anglais" étroitement couplé à notre classe TextEditor, ce qui signifie que notre classe TextEditor dépend de EnglishSpellChecker ou en d'autres termes, EnglishSpellCheker est la dépendance de TextEditor. Nous devons supprimer cette dépendance. De plus, notre éditeur de texte a besoin d'un moyen de conserver la référence concrète de tout correcteur orthographique en fonction de la discrétion du développeur au moment de l'exécution.

Ainsi, comme nous l'avons vu dans l'introduction de DI, cela suggère que la classe devrait être injectée avec ses dépendances. Donc, il devrait être de la responsabilité du code appelant d'injecter toutes les dépendances dans la classe / le code appelé. Nous pouvons donc restructurer notre code comme

interface ISpellChecker
{

    Arraylist<typos> CheckSpelling(string Text);

}

Class EnglishSpellChecker : ISpellChecker

{

    public override Arraylist<typos> CheckSpelling(string Text)

    {

        //All Magic goes here.

    }

}



Class FrenchSpellChecker : ISpellChecker

{

    public override Arraylist<typos> CheckSpelling(string Text)

    {

        //All Magic goes here.

    }

}

Dans notre exemple, la classe TextEditor doit recevoir l'instance concrète de type ISpellChecker.

Désormais, la dépendance peut être injectée dans Constructor, une propriété publique ou une méthode.

Essayons de changer notre classe en utilisant Constructor DI. La classe TextEditor modifiée ressemblera à quelque chose comme:

Class TextEditor

{

    ISpellChecker objSpellChecker;

    string Text;



    public void TextEditor(ISpellChecker objSC)

    {

        objSpellChecker = objSC;

    }



    public ArrayList <typos> CheckSpellings()

    {

        return objSpellChecker.CheckSpelling();

    }

}

Pour que le code appelant, lors de la création de l'éditeur de texte, puisse injecter le type SpellChecker approprié dans l'instance de TextEditor.

Vous pouvez lire l'article complet ici


1

La manière traditionnelle d'obtenir une instance d'adresse dans Employee serait de créer une nouvelle instance de la classe Address. Spring crée tous les objets dépendants, nous n'avons donc pas à nous soucier de l'objet.

Donc, au printemps, nous dépendons simplement du conteneur de ressort qui nous fournit l'objet de dépendance.


1

IOC est une technique dans laquelle vous laissez quelqu'un d'autre créer l'objet pour vous. Et quelqu'un d'autre en cas de printemps est le conteneur IOC.

L'injection de dépendance est une technique dans laquelle un objet fournit la dépendance d'un autre objet.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.