Quali sono i vantaggi dei contenitori per iniezione di dipendenza?

Comprendo i benefici dell’iniezione di dipendenza stessa. Prendiamo la spring, per esempio. Capisco anche i vantaggi di altre funzionalità di Spring come AOP, helper di diverso tipo, ecc. Mi chiedo, quali sono i vantaggi della configurazione XML come:

      

rispetto al semplice vecchio codice java come:

 Female mary = new Female(); mary.setAge(23); Male john = new Male(); john.setGirlfriend(mary); 

che è più facile eseguire il debug, compilare il tempo controllato e può essere compreso da chiunque conosca solo Java. Quindi qual è lo scopo principale di un framework di iniezione delle dipendenze? (o un pezzo di codice che mostra i suoi benefici).


AGGIORNARE:
In caso di

 IService myService;// ... public void doSomething() { myService.fetchData(); } 

Come può la struttura IoC indovinare quale implementazione di myService voglio essere iniettata se ce n’è più di una? Se esiste solo un’implementazione dell’interfaccia fornita e il contenitore IoC decide automaticamente di utilizzarlo, verrà interrotto dopo la visualizzazione di una seconda implementazione. E se c’è intenzionalmente solo una ansible implementazione di un’interfaccia, non è necessario iniettarla.

Sarebbe davvero interessante vedere una piccola parte della configurazione per IoC che mostra i suoi benefici. Sto usando Spring per un po ‘e non posso fornire questo esempio. E posso mostrare singole linee che dimostrano i benefici di hibernate, dwr e altri framework che uso.


AGGIORNAMENTO 2:
Mi rendo conto che la configurazione IoC può essere cambiata senza ricompilare. È davvero una buona idea? Posso capire quando qualcuno vuole cambiare le credenziali del DB senza ricompilare – potrebbe non essere uno sviluppatore. Nella tua pratica, quanto spesso qualcun altro oltre a uno sviluppatore modifica la configurazione di IoC? Penso che per gli sviluppatori non ci sia lo sforzo di ricompilare quella particolare class invece di modificare la configurazione. E per i non sviluppatori vorresti probabilmente semplificarti la vita e fornire un file di configurazione più semplice.


AGGIORNAMENTO 3:

Configurazione esterna della mapping tra le interfacce e le loro implementazioni concrete

Cosa c’è di così buono nel renderlo estenuante? Non rendi tutto il tuo codice esterno, mentre puoi sicuramente – basta inserirlo nel file ClassName.java.txt, leggere e compilare manualmente al volo – wow, hai evitato di ricompilarlo. Perché la compilazione dovrebbe essere evitata ?!

Si risparmia tempo per la codifica perché si forniscono mapping in modo dichiarativo, non in un codice procedurale

Capisco che a volte l’approccio dichiarativo consente di risparmiare tempo. Ad esempio, dichiaro solo una volta che un’associazione tra una proprietà bean e una colonna DB e hibernate utilizza questa mapping durante il caricamento, il salvataggio, la creazione di SQL basato su HSQL, ecc. Qui è dove opera l’approccio dichiarativo. In caso di Spring (nel mio esempio), la dichiarazione aveva più linee e aveva la stessa espressività del codice corrispondente. Se c’è un esempio quando tale dichiarazione è più breve del codice – mi piacerebbe vederlo.

Il principio di Inversion of Control consente un facile test delle unità perché è ansible sostituire le implementazioni reali con quelle false (come la sostituzione del database SQL con uno in-memory)

Capisco l’inversione dei benefici del controllo (preferisco chiamare il modello di progettazione qui discusso come Iniezione delle dipendenze, perché l’IoC è più generale – ci sono molti tipi di controllo e ne stiamo invertendo solo uno – il controllo dell’inizializzazione). Stavo chiedendo perché qualcuno abbia mai bisogno di qualcosa di diverso da un linguaggio di programmazione per questo. Sicuramente posso sostituire le reali implementazioni con quelle false usando il codice. E questo codice esprimerà la stessa cosa della configurazione: inizializzerà solo i campi con valori falsi.

 mary = new FakeFemale(); 

Capisco i vantaggi di DI. Non capisco quali vantaggi vengano aggiunti dalla configurazione XML esterna rispetto alla configurazione del codice che fa lo stesso. Non penso che la compilazione debba essere evitata – compilo ogni giorno e sono ancora vivo. Penso che la configurazione di DI sia un cattivo esempio di approccio dichiarativo. La dichiarazione può essere utile se viene dichiarata una volta E viene utilizzata molte volte in modi diversi, come hibernate cfg, dove il mapping tra la proprietà bean e la colonna DB viene utilizzato per salvare, caricare, creare query di ricerca, ecc. La configurazione DI di Spring può essere facilmente tradotta in configurazione del codice, come all’inizio di questa domanda, non è ansible? Ed è usato solo per l’inizializzazione del bean, non è vero? Il che significa che un approccio dichiarativo non aggiunge nulla qui, vero?

Quando dichiaro la mapping di ibernazione, do solo in ibernazione alcune informazioni, e funziona in base ad essa – non dico cosa fare. In caso di spring, la mia dichiarazione dice alla spring esattamente cosa fare – quindi perché dichiararlo, perché non farlo?


ULTIMO AGGIORNAMENTO:
Ragazzi, molte risposte mi dicono dell’iniezione di dipendenza, che so che è BUONO. La domanda riguarda lo scopo della configurazione DI invece di inizializzare il codice: tendo a pensare che il codice di inizializzazione sia più breve e più chiaro. L’unica risposta che ho ottenuto fino alla mia domanda è che evita la ricompilazione, quando la configurazione cambia. Credo che dovrei postare un’altra domanda, perché è un grande segreto per me, perché la compilazione dovrebbe essere evitata in questo caso.

Per me uno dei motivi principali per usare un IoC (e fare uso della configurazione esterna) riguarda le due aree di:

  • analisi
  • Manutenzione della produzione

analisi

Se dividi i test in 3 scenari (che è abbastanza normale nello sviluppo su larga scala):

  1. Test unitario
  2. Test d’integrazione
  3. Test della scatola nera

Quello che vorrete fare è per gli ultimi due scenari di test (Integrazione e scatola nera), non è ricompilare alcuna parte dell’applicazione.

Se uno qualsiasi dei tuoi scenari di test richiede di modificare la configurazione (ad esempio: utilizzare un altro componente per simulare un’integrazione bancaria o eseguire un carico di prestazioni), questo può essere facilmente gestito (ciò comporta i vantaggi della configurazione del lato DI di un Tuttavia, IoC.

Inoltre, se la tua app viene utilizzata su più siti (con diverse configurazioni di server e componenti) o se modifica la configurazione nell’ambiente live, puoi utilizzare le fasi successive del test per verificare che l’app gestisca tali modifiche.

Produzione

Come sviluppatore non hai (e non dovresti) avere il controllo dell’ambiente di produzione (in particolare quando la tua app viene distribuita a più clienti o siti separati), questo per me è il vero vantaggio dell’uso di un IoC e di una configurazione esterna , poiché spetta al supporto infrastrutturale / produttivo modificare e regolare l’ambiente live senza dover tornare agli sviluppatori e testare (costo più alto quando tutto ciò che vogliono è spostare un componente).

Sommario

I principali vantaggi della configurazione esterna di un IoC derivano dal fornire ad altri (non sviluppatori) il potere di configurare la propria applicazione, nella mia esperienza ciò è utile solo in un numero limitato di circostanze:

  • L’applicazione è distribuita su più siti / client in cui gli ambienti saranno diversi.
  • Controllo / input di sviluppo limitato rispetto all’ambiente di produzione e all’impostazione.
  • Scenari di test.

In pratica ho scoperto che anche quando si sviluppa qualcosa che si ha il controllo sull’ambiente su cui verrà eseguito, nel tempo è meglio dare a qualcun altro le capacità per modificare la configurazione:

  • Durante lo sviluppo non sai quando cambierà (l’app è così utile che la tua azienda lo vende a qualcun altro).
  • Non voglio rimanere bloccato con la modifica del codice ogni volta che viene richiesta una leggera modifica che potrebbe essere stata gestita impostando e utilizzando un buon modello di configurazione.

Nota: l’applicazione si riferisce alla soluzione completa (non solo all’eseguibile), quindi tutti i file necessari per l’esecuzione dell’applicazione .

L’iniezione di dipendenza è uno stile di codifica che ha le sue radici nell’osservazione che la delega degli oggetti è di solito un modello di progettazione più utile dell’ereditarietà dell’object (cioè, l’object ha una relazione più utile di quanto l’object sia una relazione). Un altro ingrediente è necessario, tuttavia, per il DI lavorare, quello di creare interfacce di oggetti. Combinando questi due potenti modelli di progettazione, gli ingegneri del software si resero presto conto che potevano creare codice flessibile e liberamente accoppiato e così nacque il concetto di Dependency Injection. Comunque non è stato fino a quando la riflessione dell’object non è diventata disponibile in certi linguaggi di alto livello che DI è davvero decollato. Il componente di riflessione è il fulcro della maggior parte dei sistemi DI oggi, perché gli aspetti davvero interessanti di DI richiedono la possibilità di selezionare a livello di codice oggetti e configurarli e iniettarli in altri oggetti utilizzando un sistema esterno e indipendente dagli oggetti stessi.

Un linguaggio deve fornire un valido supporto sia per le normali tecniche di programmazione orientate agli oggetti, sia per il supporto per le interfacce degli oggetti e la riflessione degli oggetti (ad esempio Java e C #). Mentre è ansible creare programmi utilizzando i pattern DI nei sistemi C ++, la mancanza di supporto per la riflessione all’interno del linguaggio corretto impedisce di supportare i server delle applicazioni e altre piattaforms DI e quindi limita l’espressività dei pattern DI.

Punti di forza di un sistema costruito utilizzando i modelli DI:

  1. Il codice DI è molto più facile da riutilizzare in quanto la funzionalità “dipendente” viene estrapolata in interfacce ben definite, consentendo agli oggetti separati la cui configurazione viene gestita da una piattaforma applicativa adatta per essere inseriti in altri oggetti a piacimento.
  2. Il codice DI è molto più facile da testare. La funzionalità espressa dall’object può essere testata in una scatola nera creando oggetti “mock” che implementano le interfacce previste dalla logica dell’applicazione.
  3. Il codice DI è più flessibile. È un codice innestato in modo sciolto – ad un estremo. Ciò consente al programmatore di scegliere e in che modo colbind gli oggetti basandosi esclusivamente sulle loro interfacce richieste da un lato e le loro interfacce espresse sull’altro.
  4. La configurazione esterna (Xml) degli oggetti DI significa che altri possono personalizzare il codice in direzioni impreviste.
  5. La configurazione esterna è anche una separazione del modello di preoccupazione in quanto tutti i problemi di inizializzazione dell’object e gestione dell’interdipendenza dell’object possono essere gestiti dal server delle applicazioni.
  6. Si noti che non è richiesta la configurazione esterna per utilizzare il modello DI, per le interconnessioni semplici un object piccolo costruttore è spesso adeguato. C’è un compromesso tra i due. Un object costruttore non è un’opzione flessibile come un file di configurazione visibile esternamente. Lo sviluppatore del sistema DI deve soppesare i vantaggi della flessibilità rispetto alla praticità, facendo attenzione che il controllo su piccola scala, a grana fine, sulla costruzione dell’object come express in un file di configurazione possa aumentare i costi di confusione e di manutenzione lungo la linea.

Sicuramente il codice DI sembra più ingombrante, gli svantaggi di avere tutti quei file XML che configurano gli oggetti da iniettare in altri oggetti sembra difficile. Questo è, tuttavia, il punto dei sistemi DI. La possibilità di combinare oggetti di codice come una serie di impostazioni di configurazione consente di creare sistemi complessi utilizzando codice di terze parti con codifica minima da parte dell’utente.

L’esempio fornito nella domanda si limita a toccare la superficie del potere espressivo che può essere fornita da una libreria di oggetti DI opportunamente calcasting. Con un po ‘di pratica e molta autodisciplina, la maggior parte dei professionisti di DI trova che possono build sistemi che hanno una copertura di prova del 100% del codice dell’applicazione. Questo solo punto è straordinario. Questa non è una copertura di prova del 100% di una piccola applicazione di poche centinaia di righe di codice, ma una copertura di prova del 100% delle applicazioni che comprende centinaia di migliaia di linee di codice. Sono in perdita di essere in grado di descrivere qualsiasi altro modello di progettazione che fornisce questo livello di testabilità.

Hai ragione nel dire che un’applicazione di solo 10s di linee di codice è più facile da capire rispetto a diversi oggetti più una serie di file di configurazione XML. Tuttavia, come con la maggior parte dei modelli di progettazione potenti, i guadagni si trovano man mano che si continua ad aggiungere nuove funzionalità al sistema.

In breve, le applicazioni basate su DI su larga scala sono più facili da eseguire il debug e sono più facili da capire. Mentre la configurazione dell’Xml non è ‘compilata in tempo’, tutti i servizi applicativi di cui questo autore è a conoscenza forniranno allo sviluppatore messaggi di errore se tentano di iniettare un object con un’interfaccia incompatibile in un altro object. E la maggior parte fornisce una funzione di ‘controllo’ che copre tutte le configurazioni di oggetti conosciuti. Ciò viene eseguito facilmente e rapidamente controllando che l’object A-iniettato A implementa l’interfaccia richiesta dall’object B per tutte le iniezioni di oggetti configurati.

Questa è una domanda un po ‘carica, ma io tendo ad essere d’accordo sul fatto che enormi quantità di configurazione xml non sono davvero di grande beneficio. Mi piace che le mie applicazioni siano il più leggere ansible sulle dipendenze, compresi i quadri pesanti.

Semplificano il codice un sacco di volte, ma hanno anche un sovraccarico di complessità che rende piuttosto difficile rintracciare i problemi (ho visto problemi di prima mano, e con Java diritta mi sarebbe molto più comodo trattare).

Immagino che dipenda un po ‘dallo stile, e con cosa ti trovi a tuo agio … ti piace volare con la tua soluzione e avere il vantaggio di conoscerlo a fondo, o fare affidamento su soluzioni esistenti che potrebbero rivelarsi difficili quando la configurazione non è giusto? È tutto un compromesso.

Tuttavia, la configurazione XML è un po ‘pet-friendly del mio … Cerco di evitarlo a tutti i costi.

Ogni volta che puoi modificare il tuo codice in dati, stai facendo un passo nella giusta direzione.

Codificare qualsiasi cosa come dati significa che il codice stesso è più generale e riutilizzabile. Significa anche che i tuoi dati possono essere specificati in una lingua che si adatta esattamente.

Inoltre, un file XML può essere letto in una GUI o in qualche altro strumento e facilmente manipolato in modo pragmatico. Come faresti con l’esempio di codice?

Sto costantemente prendendo in considerazione cose che la maggior parte delle persone implementerebbe come codice nei dati, rende il codice molto più pulito. Trovo inconcepibile che le persone creino un menu in codice piuttosto che come dati – dovrebbe essere ovvio che farlo in codice è semplicemente sbagliato a causa del boilerplate.

Il motivo per cui utilizzi un contenitore DI è che non devi avere un miliardo di proprietà preconfigurate nel tuo codice che sono semplicemente getter e setter. Vuoi veramente hardcode tutti quelli con la nuova X ()? Certo, puoi avere un valore predefinito, ma il contenitore DI consente la creazione di singleton che è estremamente facile e ti consente di concentrarti sui dettagli del codice, non sul compito vario di inizializzarlo.

Ad esempio, Spring consente di implementare l’interfaccia InitializingBean e aggiungere un metodo afterPropertiesSet (è anche ansible specificare un “metodo-init” per evitare l’accoppiamento del codice a Spring). Questi metodi ti permetteranno di garantire che qualsiasi interfaccia specificata come campo nell’istanza della class sia configurata correttamente all’avvio, e quindi non dovrai più controllare i tuoi getter e setter (supponendo che tu permetta ai tuoi singleton di rimanere sicuri per i thread ).

Inoltre, è molto più semplice eseguire inizializzazioni complesse con un contenitore DI invece di eseguirle da soli. Per esempio, sono d’aiuto nell’usare XFire (non CeltiXFire, usiamo solo Java 1.4). L’app utilizzava Spring, ma sfortunatamente usava il meccanismo di configurazione services.xml di XFire. Quando una raccolta di elementi necessari per dichiarare che aveva ZERO o più istanze invece di una o più istanze, ho dovuto ignorare parte del codice XFire fornito per questo particolare servizio.

Ci sono alcune impostazioni predefinite di XFire definite nello schema dei bean Spring. Quindi, se stessimo usando Spring per configurare i servizi, i bean avrebbero potuto essere usati. Invece, è successo che dovevo fornire un’istanza di una class specifica nel file services.xml invece di usare i bean. Per fare ciò, avevo bisogno di fornire il costruttore e impostare i riferimenti dichiarati nella configurazione di XFire. Il vero cambiamento che avevo bisogno di rendere necessario sovraccarico una singola class.

Ma grazie al file services.xml, ho dovuto creare quattro nuove classi, impostando i loro valori di default in base ai loro valori predefiniti nei file di configurazione Spring nei loro costruttori. Se fossimo stati in grado di usare la configurazione Spring, avrei potuto semplicemente dire:

           

Invece, assomigliava più a questo:

 public class TheFirstPointlessClass extends SomeXFireClass { public TheFirstPointlessClass() { setFirstProperty(new TheSecondPointlessClass()); setSecondProperty(new TheThingThatWasHereBefore()); } } public class TheSecondPointlessClass extends YetAnotherXFireClass { public TheSecondPointlessClass() { setFirstProperty(TheThirdPointlessClass()); } } public class TheThirdPointlessClass extends GeeAnotherXFireClass { public TheThirdPointlessClass() { setFirstProperty(new AnotherThingThatWasHereBefore()); setSecondProperty(new WowItsActuallyTheCodeThatChanged()); } } public class WowItsActuallyTheCodeThatChanged extends TheXFireClassIActuallyCareAbout { public WowItsActuallyTheCodeThatChanged() { } public overrideTheMethod(Object[] arguments) { //Do overridden stuff } } 

Quindi il risultato netto è che quattro ulteriori classi Java, per lo più inutili, dovevano essere aggiunte alla base di codice per ottenere l’effetto che una class addizionale e alcune semplici informazioni sul contenitore delle dipendenze ottenevano. Questa non è l ‘”eccezione che conferma la regola”, questa è la regola … la gestione dei capricci nel codice è molto più pulita quando le proprietà sono già fornite in un contenitore DI e le stai semplicemente modificando per adattarle a una situazione speciale, che succede più spesso.

Ho la tua risposta

Ci sono ovviamente compromessi in ogni approccio, ma i file di configurazione XML esternalizzati sono utili per lo sviluppo aziendale in cui i sistemi di compilazione vengono utilizzati per compilare il codice e non il tuo IDE. Usando il sistema di build, potresti voler inserire determinati valori nel tuo codice, ad esempio la versione della build (che potrebbe essere doloroso dover aggiornare manualmente ogni volta che compili). Il dolore è maggiore quando il tuo sistema di compilazione estrae il codice da qualche sistema di controllo della versione. La modifica di valori semplici in fase di compilazione richiede la modifica di un file, il commit, la compilazione e il ripristino di ogni volta per ogni modifica. Non si tratta di modifiche che si desidera convertire nel controllo della versione.

Altri casi d’uso utili riguardanti il ​​sistema di compilazione e le configurazioni esterne:

  • iniettare stili / fogli di stile per una singola base di codice per diverse build
  • iniettare diversi set di contenuti dinamici (o riferimenti ad essi) per il tuo singolo codice base
  • iniettare il contesto di localizzazione per diversi build / client
  • cambiare un URI webservice su un server di backup (quando quello principale si interrompe)

Aggiornamento: tutti gli esempi sopra riportati riguardavano cose che non richiedevano necessariamente dipendenze dalle classi. Ma puoi facilmente creare casi in cui sia necessario un object complesso e un’automazione, ad esempio:

  • Immagina di avere un sistema in cui monitora il traffico del tuo sito web. A seconda del numero di utenti concorrenti, triggers / distriggers un meccanismo di registrazione. Forse mentre il meccanismo è spento, un object stub viene messo al suo posto.
  • Immagina di avere un sistema di web conferencing in cui a seconda del numero di utenti, vuoi cambiare la possibilità di fare P2P a seconda del numero di partecipanti

Non è necessario ricompilare il codice ogni volta che si modifica qualcosa nella configurazione. Semplificherà la distribuzione e la manutenzione del programma. Ad esempio è ansible scambiare un componente con un altro con solo 1 modifica nel file di configurazione.

Puoi inserire una nuova implementazione per la fidanzata. Quindi, una nuova femmina può essere iniettata senza ricompilare il codice.

          

(Quanto sopra presuppone che Female e HotFemale implementino la stessa interfaccia di GirlfFriend)

Nel mondo .NET, la maggior parte dei framework IoC fornisce sia la configurazione XML che la configurazione del codice.

StructureMap e Ninject, ad esempio, utilizzano interfacce fluenti per configurare i contenitori. Non sei più costretto a utilizzare i file di configurazione XML. Spring, che esiste anche in .NET, fa molto affidamento sui file XML poiché è la sua storica interfaccia di configurazione principale, ma è ancora ansible configurare i contenitori a livello di codice.

Facilità nel combinare configurazioni parziali in una configurazione finale completa.

Ad esempio, nelle applicazioni Web, il modello, la vista e i controllori vengono in genere specificati in file di configurazione separati. Usa l’approccio dichiarativo, puoi caricare, ad esempio:

   UI-context.xml
   Model-context.xml
   Controller-context.xml

O caricare con un’interfaccia utente diversa e alcuni controller aggiuntivi:

   AlternateUI-context.xml
   Model-context.xml
   Controller-context.xml
   ControllerAdditions-context.xml

Per fare lo stesso nel codice è necessaria un’infrastruttura per combinare configurazioni parziali. Non imansible da fare nel codice, ma sicuramente più facile da fare usando un framework IoC.

Spesso, il punto importante è chi sta cambiando la configurazione dopo che il programma è stato scritto. Con la configurazione in codice si presuppone implicitamente che la persona che lo modifica abbia le stesse competenze e l’accesso al codice sorgente ecc. Di quello dell’autore originale.

Nei sistemi di produzione è molto pratico estrarre alcuni sottoinsiemi di impostazioni (es. Età nell’esempio) in un file XML e consentire ad esempio all’amministratore di sistema o al supporto personale di modificare il valore senza dare loro pieno potere sul codice sorgente o altre impostazioni – o semplicemente per isolarli dalle complessità.

Da una prospettiva di spring posso darti due risposte.

Innanzitutto la configurazione XML non è l’unico modo per definire la configurazione. La maggior parte delle cose può essere configurata usando le annotazioni e le cose che devono essere fatte con XML sono la configurazione per il codice che non state scrivendo comunque, come un pool di connessioni che state usando da una libreria. Spring 3 include un metodo per definire la configurazione DI utilizzando Java simile alla configurazione DI ruotata a mano nel tuo esempio. Quindi, usare Spring non significa che devi usare un file di configurazione basato su XML.

In secondo luogo, la spring è molto più di un semplice framework DI. Ha molte altre funzionalità tra cui la gestione delle transazioni e AOP. La configurazione XML di Spring unisce tutti questi concetti insieme. Spesso nello stesso file di configurazione sto specificando le dipendenze dei bean, le impostazioni delle transazioni e l’aggiunta di bean con scope di sessione effettivamente gestiti utilizzando AOP in background. Trovo che la configurazione XML fornisce un posto migliore per gestire tutte queste funzionalità. Ritengo inoltre che la configurazione basata su annotazioni e la configurazione XML migliorino maggiormente rispetto alla configurazione basata su Java.

Ma vedo il tuo punto e non c’è niente di sbagliato nel definire la configurazione di injection dependency in Java. I normally do that myself in unit tests and when I’m working on a project small enough that I haven’t added a DI framework. I don’t normally specify configuration in Java because to me that’s the kind plumbing code that I’m trying to get away from writing when I chose to use Spring. That’s a preference though, it doesn’t mean that XML configuration is superior to Java based configuration.

Spring also has a properties loader. We use this method to set variables that are dependant on the environment (eg development, testing, acceptance, production, …). This could be for example the queue to listen to.

If there is no reason why the property would change, there is also no reason to configure it in this way.

Your case is very simple and therefore doesn’t need an IoC (Inversion of Control) container like Spring. On the other hand, when you “program to interfaces, not implementations” (which is a good practice in OOP), you can have code like this:

 IService myService; // ... public void doSomething() { myService.fetchData(); } 

(note that the type of myService is IService — an interface, not a concrete implementation). Now it can be handy to let your IoC container automatically provide the correct concrete instance of IService during initialization – when you have many interfaces and many implementations, it can be cumbersome to do that by hand. Main benefits of an IoC container (dependency injection framework) are:

  • External configuration of mapping between interfaces and their concrete implementations
  • IoC container handles some tricky issues like resolving complicated dependency graphs, managing component’s lifetime etc.
  • You save coding time because you provide mappings declaratively, not in a procedural code
  • Inversion of Control principle allows for easy unit testing because you can replace real implementations with fake ones (like replacing SQL database with an in-memory one)

Initializing in an XML config file will simplify your debugging / adapting work with a client who has your app deployed on their computers. (Because it doesn’t require recompilation + binary files replacement)

One of the most appealing reasons is the ” Hollywood principle “: don’t call us, we’ll call you. A component is not required to do the lookups to other components and services itself; instead they are provided to it automatically. In Java, this means that it is no longer necessary to do JNDI lookups inside the component.

It is also lots easier to unit test a component in isolation: instead of giving it an actual implementation of the components it needs, you simply use (possibly auto generated) mocks.