Cenni sulla Dependency Injection

Dependency Injection
G.Morreale

Introduzione:

La Dependency Injection è un pattern di programmazione, nello specifico è una particolare forma del pattern Inversion Of Control.
Con la Dependency Injection una classe o un sistema non è responsabile circa l'inizializzazione delle proprie dipendenze.

Cercherò prima di fare un pò di chiarezza sui termini.

Cos'è una "Dependency"?.. Banalmente è un modo diverso di chiamare le variabili di un classe, i suoi campi, o se si preferisce la variabili di istanza.

public class Esempio
{
private Risorsa risorsa;

public void Esempio()
{}

public void foo()
{
..
risorsa.faiQualcosa();
..
}
}


risorsa è una Dependency.

Cos'è "Injection"?..Non è altro che l'inizializzazione della variabile o se si vuole della Dependency!

Per realizzare una Dependency Injection attraverso il costruttore possiamo modificare l'esempio nel seguente modo:

public class Esempio
{
private Risorsa risorsa;

public void Esempio(Risorsa r)
{risorsa = r;}

public void foo()
{
..
risorsa.faiQualcosa();
..
}
}


L'injection avviene quando all'esterno della classe che contiene la Dependency (la variabile di istanza da inizializzare) si passa la dependency stessa già inizializzata.

public class EsempioTest
{
public void Test()
{
Risorsa r = new Risorsa("bla bla");
Esempio esempio = new Esempio(r);
esempio .foo();
}
}


In questo caso la Dependecy Injection è avvenuta tramite costruttore, ma tale tecnica può essere realizzata con un metodo "set" o tramite l'interfaccia.

Esistono infatti 3 tipi di Depency Injection:

  • Constructor Injection
  • Setter Injection
  • Interface Injection

A cosa serve la Dependency Injection?

L'obiettivo di tale tecnica è quello di allentare l'associazione(coupling) tra un oggetto e ed un altro.
Per approfondire circa l'utilità del pattern è consigliabile la lettura di questo articolo http://docs.google.com/View?docid=dg4p5693_22h76wp

La riduzione della dipendenza tra una classe e l'altra, inoltre, facilita le fasi di unit testing rendendo tale pattern adatto per progetti basati sul Test Driven Development(http://www.javaportal.it/rw/43650/editorial.html )

Dependency Injection e Java EE

Nella versione J2EE 1.4 si utilizzava la tecnica del JNDI lookup, la classe che intendeva usare una risorsa/servizio doveva dichiarare esplicitamente tale dipendenza e ottenerla attraverso il JNDI lookup.

Context ic = new InitialContext();
HelloWorld helloWorld = (HelloWorld)ic.lookup("java:comp/env/ejb/HelloWorld");

Con le nuove specifiche è il container che si occupa di effettuare tale lookup e inizializzazione per conto della classe che intende usare tale dipendenza. La classe deve solo indicare che intende usare la dipendenza:

@EJB
private HelloWord hello;


altri esempi

@PersistenceContext
private EntityManager em;

@WebServiceRef
private SmsWebService service;

Le annotation (@EJB, @PersistenceContext etc.) supportano dei parametri che consentono di indicare al container il nome della risorsa, la tipologia e altre opzioni. Ad esempio nel caso del PersistenceContext, nel caso in cui esistono all'interno del modulo ejb due diversi persistence unit è necessario indicare il nome del persistence unit da utilizzare.

@PersistenceContext(unitName="p1")
private EntityManager em1;

@PersistenceContext(unitName="p2")
private EntityManager em2;

Visto che il responsabile di tale operazione di "Injection" è il container il pattern può essere usato solo per le classi managed, quelle unmanaged useranno,ad esempio, la tecnica del JNDI lookup.

Di seguito la lista delle managed class divise per tipologia di container(Web/EJB)

Web (Tipi di risorsa validi per l'injection: DataSource, JMS, Mail, EJB, Environment entries, EntityManager, UserTransaction)
  • Servlet,
  • listener classes,
  • web services end-point,
  • JAX-RPC handlers

EJB (Tipi di risorsa validi per l'injection:DataSource, JMS, Mail, Environment entries, EntityManager, EJB Context, UserTransaction, TimerService)
  • Bean,
  • interceptors,
  • web services end-point

Conclusione

Conoscere la Dependency Injection quindi serve a capire quali meccanismi stanno dietro l'inizializzazione invisibile di quei particolari campi preceduti dall'annotation(@EJB, @TimerService etc.)

Inoltre è possibile in fase di design dei propri progetti implementare tale pattern qualora si necessario disaccoppiare le componenti del progetto.

No comments: