
Originariamente inviata da
gaten
ti posso chiedere un esempio?
Inoltre quando dici che è coinvolto con il discorso della Dipendency Injection, in che senso?
Un concetto fondamentale alla base di Spring è la Dependency Injection. Questa tecnica sostanzialmente inverte ciò che si farebbe normalmente per assegnare delle dipendenze (cioè altri oggetti necessari) ad un certo oggetto.
Lo scenario senza DI è questo. Immagina una classe A che ha bisogno di una classe B per poter fare qualcosa. Questo è un codice basilare:
codice:
package com.esempio;
public class A {
private B b;
public A() {
b = new B();
}
public void faiQualcosaConB() {
// qui usa b
}
}
codice:
package com.esempio;
public class B {
// .......
}
Fin qui nulla di strano, è puro e normalissimo codice Java. Però vedi bene quella istanziazione nel costruttore:
b = new B();
C'è qualcosa di male? Di per sé no, nel senso che è il minimo da fare e in contesti piccoli/normali può anche andare bene. La questione è che qui è la classe A che si sta preoccupando di ottenere le dipendenze, in questo caso solo un oggetto B. Un oggetto di un'altra classe lo si può ottenere in vari modi: se ha un costruttore pubblico, invocandolo. Se la classe fosse un "singleton", avrebbe il costruttore privato e offrirebbe un es. getInstance() statico pubblico per cui si farebbe b = B.getInstance();
O in altri modi. Il succo non cambia: è la classe A che ha del codice interno per creare/ottenere le dipendenze di cui ha bisogno.
In progetti e contesti di un certo livello però questo fatto pone diversi problemi.
E se io volessi testare il comportamento della classe A? Testerei ed eseguirei implicitamente anche quello che fa la classe B. Ma immagina che B faccia accesso ad un DB. Se io testo la classe A, NON voglio che si vada realmente su un DB. Vorrei che la classe A avesse un oggetto B "fittizio" che non va realmente su DB ma risponda alle richieste come voglio io, potendo simulare un successo, un errore o altro.
Peccato che non si può. La classe A fa new B(), questo è il problema. Questo è cablato nel codice di A e non lo puoi cambiare così su due piedi.
E se volessi che in base ad una certa configurazione esterna, invece di un oggetto B si possa usare una sua sottoclasse BPlus ? Idem non si può. A istanzia un B e non "sa" nulla di BPlus.
Con la DI invece lo scenario cambia: NON è più A che si preoccupa di ottenere le dipendenze ma è "qualcun'altro" che dà ad A le dipendenze. Come? Banalmente tramite un costruttore o un metodo "setter". Chiaramente la classe A deve essere scritta per facilitare e permettere la DI.
Nell'esempio, basta cambiare A in:
codice:
package com.esempio;
public class A {
private B b;
public A(B b) {
this.b = b;
}
public void esegui() {
// qui si usa b
}
}
Anche qui è normalissimo codice Java, che si potrebbe anche usare con altro normale codice Java:
B unB = new B();
A unA = new A(unB);
Ma in questo caso non c'è alcuna DI fatta da un framework con un suo contenitore. Ripeto, fin qui è normalissimo e comunissimo codice Java.

Originariamente inviata da
gaten
Cioè che posso avere constructor injection o metodi di setter injection nei miei oggetti bean?
Sì, appunto ... ci sto arrivando. 
Con Spring puoi avere un file XML (qui metto solo la parte dei bean, ma serve anche tutta la dichiarazione standard XML iniziale):
codice:
<bean id="unA" class="com.esempio.A">
<constructor-arg ref="unB"/>
</bean>
<bean id="unB" class="com.esempio.B"/>
In questo modo Spring: istanzia prima B (capisce che è una dipendenza per A), poi istanzia A usando il costruttore che riceve l'oggetto B. L'oggetto A potrebbe poi essere tirato fuori dal container esplicitamente oppure iniettato a sua volta in un altro oggetto.
Alla fine è tutto qui, come concetto.

Originariamente inviata da
gaten
Com'è composto questo container?
A livello interno, proprio materialmente, non lo so. È sicuramente una "mappa" nel senso di associazione, perché in Spring ciascun bean è associato ad un nome (una stringa, è quel id) e opzionalmente a N "alias".