Che cos'è l'inserimento delle dipendenze e l'inversione del controllo in Spring Framework?


112

"Dependency Injection" e "Inversion of Control" sono spesso menzionati come i principali vantaggi dell'utilizzo del framework Spring per lo sviluppo di framework Web

Qualcuno potrebbe spiegare di cosa si tratta in termini molto semplici con un esempio, se possibile?



3
@SteveChambers non è duplicato, questa domanda viene posta in Springs Perspective. Questa domanda è in prospettiva generale.
VdeX

Risposte:


233
  • Spring aiuta nella creazione di applicazioni debolmente accoppiate a causa di Dependency Injection .
  • In primavera, gli oggetti definiscono le loro associazioni (dipendenze) e non si preoccupano di come otterranno tali dipendenze . È responsabilità di Spring fornire le dipendenze richieste per la creazione di oggetti.

Ad esempio : supponiamo di avere un oggetto Employeee che abbia una dipendenza dall'oggetto Address. Definiremmo un bean corrispondente a Employeequello che definirà la sua dipendenza dall'oggetto Address.

Quando Spring prova a creare un Employeeoggetto, vedrà che Employeeha una dipendenza da Address, quindi creerà prima l' Addressoggetto (oggetto dipendente) e poi lo inietterà Employeenell'oggetto.

  • Inversion of Control ( IoC ) e Dependency Injection ( DI ) vengono utilizzati in modo intercambiabile. IoC si ottiene tramite DI. DI è il processo di fornitura delle dipendenze e IoC è il risultato finale di DI. ( Nota: DI non è l'unico modo per ottenere IoC. Ci sono anche altri modi .)

  • Da DI, la responsabilità della creazione di oggetti viene spostata dal codice della nostra applicazione al contenitore Spring; questo fenomeno è chiamato IoC.

  • L'iniezione delle dipendenze può essere eseguita tramite l'iniezione setter o l'iniezione del costruttore.

Non sono d'accordo. non credo che questa sia una spiegazione chiara. Perché non puoi semplicemente istanziare "Indirizzo" in "Dipendente" invece di ottenere un framework per crearlo e iniettarlo? È necessario un esempio leggermente più dettagliato.
Boris

2
@ Boris Nessuno ha detto che non puoi istanziare i tuoi oggetti. Ma l'unico scopo della risposta era dimostrare come puoi ottenere lo stesso con DI. È possibile creare istanze sia di DI che di oggetti dal codice client. Questo sarebbe ancora chiamato IOC, almeno parzialmente.
bogdan.rusu


Boris. Molto geloso? Questa è la migliore risposta in assoluto.
Aniket Kapse

31

Scriverò la mia semplice comprensione di questi due termini: (Per una rapida comprensione leggi solo esempi)

  • Dependency Injection (DI): l'
    inserimento di dipendenze generalmente significa passare un oggetto dipendente come parametro a un metodo, piuttosto che fare in modo che il metodo crei l'oggetto dipendente .
    Ciò che significa in pratica è che il metodo non ha una dipendenza diretta da una particolare implementazione; qualsiasi implementazione che soddisfi i requisiti può essere passata come parametro.

    Con questa implementazione degli oggetti definisce le loro dipendenze. E la primavera lo rende disponibile.
    Questo porta allo sviluppo di applicazioni liberamente accoppiate.

    Esempio rapido: OGGETTO DIPENDENTE QUANDO È CREATO, CREA AUTOMATICAMENTE L'OGGETTO INDIRIZZO (se l'indirizzo è definito come dipendenza dall'oggetto Dipendente) *.

  • Contenitore Inversion of Control (IoC):
    questa è una caratteristica comune dei framework, IoC gestisce gli oggetti java , dall'istanziazione
    alla distruzione attraverso la sua BeanFactory.
    - I componenti Java istanziati dal contenitore IoC sono chiamati bean e il contenitore IoC gestisce l'ambito di un bean, gli eventi del ciclo di vita e qualsiasi funzionalità AOP per cui è stato configurato e codificato.

    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.

    Implementando l'inversione del controllo, un consumatore di software / oggetto ottiene più controlli / opzioni sul software / oggetti, invece di essere controllato o avere meno opzioni.

    L'inversione del controllo come linea guida di progettazione ha i seguenti scopi:
    - Esiste un disaccoppiamento tra l'esecuzione di un determinato compito e l'implementazione.
    - Ogni modulo può concentrarsi su ciò per cui è stato progettato.
    - I moduli non fanno supposizioni su ciò che fanno gli altri sistemi ma si basano sui loro contratti.
    - La sostituzione dei moduli non ha effetti collaterali su altri moduli

Manterrò le cose astratte qui, puoi visitare i seguenti collegamenti per una comprensione dettagliata dell'argomento.

Una buona lettura con l'esempio

Spiegazione dettagliata


11

In Spring gli oggetti sono liberamente accoppiati, cioè ogni classe è indipendente l'una dall'altra in modo che tutto possa essere testato individualmente. Ma quando si usano queste classi, una classe può dipendere da altre classi che devono essere istanziate per prime.

Quindi, diciamo a Spring che la classe A dipende dalla classe B.Quindi, quando si crea un bean (come la classe) per la classe A, istanzia la classe B prima di quella della classe A e la inserisce nella classe A usando metodi setter o costruttore DI. Cioè, stiamo dicendo alla primavera la dipendenza in fase di esecuzione. Questo è DI.

Poiché stiamo assegnando la responsabilità di creare oggetti (bean), mantenerli e le loro aggregazioni a Spring invece di codificarlo, lo chiamiamo Inversion Of Control (IOC).


7

Inversion Of Control (IOC):

IoC è un modello di progettazione che descrive l'inversione del flusso di controllo in un sistema, quindi il flusso di esecuzione non è controllato da una parte centrale di codice. Ciò significa che i componenti dovrebbero dipendere solo dalle astrazioni di altri componenti e non sono responsabili della gestione della creazione di oggetti dipendenti. Invece, le istanze degli oggetti vengono fornite in fase di esecuzione da un contenitore IoC tramite Dependency Injection (DI).

IoC consente una migliore progettazione del software che facilita il riutilizzo, l'accoppiamento libero e il facile test dei componenti software.

Iniezione di dipendenza (DI):

DI è una tecnica per passare le dipendenze nel costruttore di un oggetto. Se l'oggetto è stato caricato dal contenitore, le sue dipendenze verranno fornite automaticamente dal contenitore. Ciò consente di utilizzare una dipendenza senza dover creare manualmente un'istanza. Ciò riduce l'accoppiamento e offre un maggiore controllo sulla durata delle istanze degli oggetti.

clicca per vedere di più


6

Spring: Spring è il contenitore "Inversion of Control" per la piattaforma Java.

Inversion of Control (IoC): Inversion of Control (IoC) è una pratica di programmazione orientata agli oggetti in cui l'accoppiamento di oggetti è limitato in fase di esecuzione da un oggetto "assembler" e in genere non è conoscibile in fase di compilazione utilizzando l'analisi statica.

Dependency Injection (DI): "Dependency injection è un modello di progettazione software che consente la rimozione di dipendenze hard-coded e rende possibile modificarle, sia in fase di esecuzione che in fase di compilazione." -wiki.


Come è più semplice di ciò che è già disponibile (da dove proviene questa risposta)? Non tiene conto della richiesta di semplicità dell'OP, a meno che le doppie virgolette intorno alle terminologie non rendano magicamente le cose più semplici.
Fiamma di udun

6

Inversione del controllo: significa dare il controllo della creazione e istanziazione dei bean spring al contenitore Spring IOC e l'unico lavoro che lo sviluppatore fa è configurare i bean nel file xml spring.

Iniezione di dipendenza-

Considera un impiegato di classe

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

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


}

e considera l'indirizzo di classe

class Address {
   private String street;
   private String city;

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

  }
}

Nel codice precedente i valori della classe dell'indirizzo verranno impostati solo quando viene creata un'istanza della classe Employee, che è la dipendenza della classe Address dalla classe Employee. E spring risolve questo problema utilizzando il concetto di Dependency Injection fornendo due modi per iniettare questa dipendenza.

  1. Iniezione di setter

Metodo setter nella classe Employee che accetta un riferimento alla classe Address

public void setAddress(Address addr) {
    this.address = addr;
}
  1. Iniezione nel costruttore

Costruttore nella classe Employee che accetta Address

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

In questo modo i valori della classe Address possono essere impostati in modo indipendente utilizzando sia l'inserimento che il costruttore.


3

L'inversione del controllo è un principio di progettazione generico dell'architettura software che aiuta nella creazione di framework software riutilizzabili e modulari di facile manutenzione.

È un principio di progettazione in cui il flusso di controllo viene "ricevuto" dalla libreria scritta generica o dal codice riutilizzabile.

Per capirlo meglio, vediamo come eravamo abituati a programmare nei nostri primi giorni di codifica. Nei linguaggi procedurali / tradizionali, la logica aziendale controlla generalmente il flusso dell'applicazione e "richiama" il codice / le funzioni generici o riutilizzabili. Ad esempio, in una semplice applicazione Console, il mio flusso di controllo è controllato dalle istruzioni del mio programma, che possono includere le chiamate ad alcune funzioni generali riutilizzabili.

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

In Contrast, con IoC, i Frameworks sono il codice riutilizzabile che "chiama" la logica aziendale.

Ad esempio, in un sistema basato su Windows, sarà già disponibile un framework per creare elementi dell'interfaccia utente come pulsanti, menu, finestre e finestre di dialogo. Quando scrivo la logica di business della mia applicazione, saranno gli eventi del framework a chiamare il mio codice di logica di business (quando viene generato un evento) e NON il contrario.

Sebbene il codice del framework non sia a conoscenza della mia logica aziendale, saprà comunque come chiamare il mio codice. Ciò si ottiene utilizzando eventi / delegati, callback ecc. Qui il controllo del flusso è "invertito".

Quindi, invece di dipendere dal flusso di controllo su oggetti vincolati staticamente, il flusso dipende dall'oggetto grafico complessivo e dalle relazioni tra oggetti diversi.

Dependency Injection è un modello di progettazione che implementa il principio IoC per risolvere le dipendenze degli oggetti.

In parole più semplici, quando provi a scrivere codice, creerai e utilizzerai classi diverse. Una classe (Classe A) può utilizzare altre classi (Classe B e / o D). Quindi, le classi B e D sono dipendenze della classe A.

Una semplice analogia sarà un'auto di classe. Un'auto potrebbe dipendere da altre classi come motore, pneumatici e altro.

Dependency Injection suggerisce che invece delle classi dipendenti (Class Car qui) che creano le sue dipendenze (Class Engine e class Tyre), la classe dovrebbe essere iniettata con l'istanza concreta della dipendenza.

Comprendiamo con un esempio più pratico. Considera che stai scrivendo il tuo TextEditor. Tra le altre cose, puoi avere un correttore ortografico che fornisce all'utente la possibilità di controllare gli errori di battitura nel suo testo. Una semplice implementazione di tale codice può essere:

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;

    }

}

A prima vista, tutto sembra roseo. L'utente scriverà del testo. Lo sviluppatore acquisirà il testo e chiamerà la funzione CheckSpellings e troverà un elenco di errori di battitura che mostrerà all'utente.

Tutto sembra funzionare alla grande fino a quando un bel giorno quando un utente inizia a scrivere in francese nell'editor.

Per fornire il supporto per più lingue, abbiamo bisogno di più correttori ortografici. Probabilmente francese, tedesco, spagnolo ecc.

Qui, abbiamo creato un codice strettamente accoppiato con il correttore ortografico "inglese" strettamente associato alla nostra classe TextEditor, il che significa che la nostra classe TextEditor dipende da EnglishSpellChecker o in altre parole EnglishSpellCheker è la dipendenza per TextEditor. Dobbiamo rimuovere questa dipendenza. Inoltre, il nostro editor di testo ha bisogno di un modo per mantenere il riferimento concreto di qualsiasi correttore ortografico basato sulla discrezione dello sviluppatore in fase di esecuzione.

Quindi, come abbiamo visto nell'introduzione di DI, suggerisce che la classe dovrebbe essere iniettata con le sue dipendenze. Quindi, dovrebbe essere responsabilità del codice chiamante iniettare tutte le dipendenze nella classe / codice chiamato. Quindi possiamo ristrutturare il nostro codice come

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.

    }

}

Nel nostro esempio, la classe TextEditor dovrebbe ricevere l'istanza concreta del tipo ISpellChecker.

Ora, la dipendenza può essere iniettata in Constructor, una proprietà pubblica o un metodo.

Proviamo a cambiare la nostra classe usando Constructor DI. La classe TextEditor modificata avrà un aspetto simile a:

Class TextEditor

{

    ISpellChecker objSpellChecker;

    string Text;



    public void TextEditor(ISpellChecker objSC)

    {

        objSpellChecker = objSC;

    }



    public ArrayList <typos> CheckSpellings()

    {

        return objSpellChecker.CheckSpelling();

    }

}

In modo che il codice chiamante, durante la creazione dell'editor di testo, possa iniettare il tipo di spellChecker appropriato nell'istanza di TextEditor.

Puoi leggere l'articolo completo qui


1

Il modo tradizionale per ottenere l'istanza dell'indirizzo in Employee sarebbe creare una nuova istanza della classe Address. Spring crea tutti gli oggetti dipendenti da noi, quindi non dobbiamo preoccuparci dell'oggetto.

Quindi in primavera dipendiamo solo dal contenitore della primavera che ci fornisce l'oggetto dipendenza.


1

Il CIO è la tecnica in cui permetti a qualcun altro di creare l'oggetto per te. E qualcun altro in caso di primavera è il contenitore IOC.

L'inserimento delle dipendenze è una tecnica in cui un oggetto fornisce la dipendenza di un altro oggetto.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.