1 dependency injection sandro pedrazzini approfondimento dependency injection

59
1 Dependency Injection Sandro Pedrazzini Approfondiment o Dependency Injection

Upload: nilda-pagani

Post on 02-May-2015

283 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

1 Dependency InjectionSandro Pedrazzini

Approfondimento

Dependency Injection

Page 2: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

2 Dependency InjectionSandro Pedrazzini

Dependency Injection (DI)

• Modalità di configurazione di un oggetto, in cui le dipendenze dell’oggetto vengono specificate da entità esterne

• L’alternativa è che l’oggetto stesso si definisca da solo, al suo interno, le dipendenze

• Anche chiamata Inversion of Control (IoC), che però ha un significato più esteso (principio del framework in generale)

Page 3: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

3 Dependency InjectionSandro Pedrazzini

Esempio

• Classe che gestisce l’esecuzione del pagamento di un certo ordine (BillingService)

• Sia la classe responsabile dell’elaborazione dei dati della carta di credito (CreditCardProcessor), sia la classe responsabile di mantenere le informazioni di log (TransactionLog) del pagamento devono poter essere modificate

Page 4: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

4 Dependency InjectionSandro Pedrazzini

Esempio (2)

Page 5: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

5 Dependency InjectionSandro Pedrazzini

Esempio (2)

• BillingService carica l’ordine sulla carta di credito. La transazione verrà registrata (log) sia in caso di riuscita, sia in caso di insuccesso

public interface IBillingService {

Receipt chargeOrder(Order order, CreditCard creditCard);

}

Page 6: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

6 Dependency InjectionSandro Pedrazzini

Esempio (3)

• Schema di elaborazione

public Receipt chargeOrder(Order order, CreditCard creditCard) { … ChargeResult result = processor.process(order.getAmount(), creditCard);

transactionLog.logChargeResult(result);

…}

Page 7: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

7 Dependency InjectionSandro Pedrazzini

Esempio (4)

public class BillingService implements IBillingService {

public Receipt chargeOrder(Order order, CreditCard creditCard) { ICreditCardProcessor processor = new PaypalCreditCardProcessor(); ITransactionLog transactionLog = new DatabaseTransactionLog();

try { ChargeResult result = processor. process(order.getAmount(), creditCard); transactionLog.logChargeResult(result);

return ...

} catch (UnreachableException e) { ... } }}

Page 8: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

8 Dependency InjectionSandro Pedrazzini

Esempio (4)

Situazione attuale

Page 9: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

9 Dependency InjectionSandro Pedrazzini

Commenti

• Il codice precedente pone problemi di modularità e di test

• La dipendenza diretta, in compilazione, all’elaboratore di carta di credito significa che ogni chiamata al codice, anche durante il test, esegue una transazione reale sulla carta di credito

ICreditCardProcessor processor = new PaypalCreditCardProcessor();

Page 10: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

10 Dependency InjectionSandro Pedrazzini

Obiettivo

Page 11: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

11 Dependency InjectionSandro Pedrazzini

Factory

• Una factory permette di separare la classe client (BillingService) dalla classe che implementa un servizio (classi concrete di CreditCardProcessor e TransactionLog)

• Una factory semplice utilizza alcuni metodi static per stabilire quale implementazione collegare a una data interface

Page 12: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

12 Dependency InjectionSandro Pedrazzini

Factory (2)

public class CreditCardProcessorFactory { private static ICreditCardProcessor instance; public static void setInstance(ICreditCardProcessor processor) { instance = processor; }

public static ICreditCardProcessor getInstance() { if (instance == null) { throw new IllegalStateException("Factory not initialized”); } return instance; }}

Page 13: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

13 Dependency InjectionSandro Pedrazzini

Factory (3)

public class RealBillingService implements IBillingService {

public Receipt chargeOrder(Order order, CreditCard creditCard) { ICreditCardProcessor processor = CreditCardProcessorFactory.getInstance(); ITransactionLog transactionLog = TransactionLogFactory.getInstance();

try { ChargeResult result = processor.process(order.getAmount(), creditCard); transactionLog.logChargeResult(result);

return ...

} catch (UnreachableException e) { ... } }}

Page 14: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

14 Dependency InjectionSandro Pedrazzini

Factory (4)

CreditCardFactory

TransactionLogFactory

Page 15: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

15 Dependency InjectionSandro Pedrazzini

Factory (5)

• La scelta dell’implementazione di ICreditCardProcessor e ITransactionLog viene fatta attraverso le factory

• In questo modo si diminuisce la dipendenza esistente tra BillingService e queste classi

• L’implementazione dei test diventa più semplice

Page 16: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

16 Dependency InjectionSandro Pedrazzini

Unit Test

public class BillingServiceTest extends TestCase { private ITransactionLog transactionLog = new InMemoryTransactionLog(); private ICreditCardProcessor processor = new FakeCreditCardProcessor();

public void setUp() { TransactionLogFactory.setInstance(transactionLog); CreditCardProcessorFactory.setInstance(processor); }

@Test public void testBilling() { ... }

public void tearDown() { TransactionLogFactory.setInstance(null); CreditCardProcessorFactory.setInstance(null); }

Page 17: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

17 Dependency InjectionSandro Pedrazzini

Unit Test (2)

...

@Test public void testBilling() { IBillingService billingService = new BillingService(); Order order = new PizzaOrder(100); CreditCard creditCard = new CreditCard("1234", 11, 2010);

Receipt receipt = billingService.chargeOrder(order, creditCard);

assertTrue(receipt.hasSuccessfulCharge()); assertEquals(100, receipt.getAmountOfCharge()); assertTrue(transactionLog.successfullyLogged()); }}

Page 18: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

18 Dependency InjectionSandro Pedrazzini

Commenti

• Codice problematico: le implementazioni vengono praticamente gestite in variabili globali (static)

• Se il tearDown() dovesse venir interrotto per qualche motivo, avremmo l’implementazione di test che rimane nella factory e potrebbe creare problemi ad altri test

• Non è possibile eseguire più test in parallelo (variabili static)

Page 19: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

19 Dependency InjectionSandro Pedrazzini

Commenti (2)

• La dipendenza è nascosta nel codice

• Se per un motivo qualsiasi la factory venisse inizializzata in modo sbagliato, bisognerebbe attendere il primo pagamento per accorgersi del problema

• La cosa si complicherebbe se il numero di factory dovesse crescere

Page 20: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

20 Dependency InjectionSandro Pedrazzini

Dependency Injection

• Con questo pattern si fa un passo ulteriore verso la separazione tra comportamento e risoluzione della dipendenza

• BillingService non è più responsabile della risoluzione, perché gli oggetti ICreditCardProcessor e ITransactionLog vengono passati come parametri

Page 21: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

21 Dependency InjectionSandro Pedrazzini

Dependency Injection (2)

• Gli oggetti dipendenti vengono forniti a BillingService dall’esterno, attraverso il costruttore (o attraverso un metodo set())

public BillingService(ICreditCardProcessor creditCardProcessor, ITransactionLog transactionLog) { fCreditCardProcessor = creditCardProcessor; fTransactionLog = transactionLog;}

Page 22: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

22 Dependency InjectionSandro Pedrazzini

Dependency Injection (3)

public class BillingService implements IBillingService { private ICreditCardProcessor fCreditCardProcessor; private ITransactionLog fTransactionLog;

public BillingService(ICreditCardProcessor creditCardProcessor, ITransactionLog transactionLog) { fCreditCardProcessor = creditCardProcessor; fTransactionLog = transactionLog; }

public Receipt chargeOrder(Order order, CreditCard creditCard) { try { ChargeResult result= fCreditCardProcessor.process(order.getAmount(), creditCard); fTransactionLog.logChargeResult(result);

return ... } catch (Exception e) { ... } }}

Page 23: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

23 Dependency InjectionSandro Pedrazzini

Dependency Injection (4)

Injector

Page 24: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

24 Dependency InjectionSandro Pedrazzini

Commenti

• Non vengono più usate factory, quindi eliminata la dipendenza tra BilingService e factory

• Si possono modificare i test, eliminando setUp() e tearDown()

Page 25: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

25 Dependency InjectionSandro Pedrazzini

Unit test

public class BillingServiceTest {

private ICreditCardProcessor processor = new FakeCreditCardProcessor(); private ITransactionLog transactionLog = new InMemoryTransactionLog(); public void testSuccessfulCharge() { Order order = new PizzaOrder(100); CreditCard creditCard = new CreditCard("1234", 11, 2010);

IBillingService billingService = new BillingService(processor, transactionLog);

Receipt receipt = billingService.chargeOrder(order, creditCard);

assertTrue(receipt.hasSuccessfulCharge()); assertEquals(100, receipt.getAmountOfCharge()); assertTrue(transactionLog.successfullyLogged()); }}

Page 26: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

26 Dependency InjectionSandro Pedrazzini

Commenti

• Con il passaggio delle dipendenze al costruttore, per ogni nuova dipendenza si deve aggiungere un parametro. In questo modo il compilatore ci può avvertire se nel test ci sono dipendenze da inserire: le dipendenze vengono esposte via API

• Ora le classi client di IBillingService devono gestire loro le dipendenze

Page 27: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

27 Dependency InjectionSandro Pedrazzini

Generalizzazione

• Si può andare indietro nella catena di dipendenze (classi che dipendono da un’implementazione di IBillingService)

• Queste classi dovranno accettare IBillingService come parametro

• Il punto di fermata saranno le classi “top-level”

Page 28: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

28 Dependency InjectionSandro Pedrazzini

Generalizzazione (2)

• Per gestire le dipendenze nelle classi “top-level” è utile usare un framework, che aiuti a ricostruire la gerarchia di dipendenze

• Ne esistono diversi– Bean Container di Spring– Guice– PicoContainer– …

Page 29: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

29 Dependency InjectionSandro Pedrazzini

DI con Guice

• Il pattern DI permette di scrivere codice più modulare e più facilmente testabile

• Framework come Guice ne facilitano l’implementazione

• Permettono di associare le interface alle implementazioni necessarie nei vari contesti

Page 30: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

30 Dependency InjectionSandro Pedrazzini

DI con Guice (2)

• La configurazione è specificata in un modulo Guice, una classe che implementa l’interfaccia Module

public class BillingModule extends AbstractModule { protected void configure() { bind(ITransactionLog.class).to(DatabaseTransactionLog.class); bind(ICreditCardProcessor.class).to(PaypalCreditCardProcessor.class);

bind(IBillingService.class).to(BillingService.class); }}

Page 31: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

31 Dependency InjectionSandro Pedrazzini

DI con Guice (3)

• Inserendo @Inject nel costruttore di BillingService, si indica a Guice di passare le dipendenze come specificate nel modulo

• Nota: non è necessario che le dipendenze vengano specificate con interface. La relazione classe-sottoclasse basta

Page 32: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

32 Dependency InjectionSandro Pedrazzini

DI con Guice (4)

public class BillingService implements IBillingService { private ICreditCardProcessor fCreditCardProcessor; private ITransactionLog fTransactionLog;

@Inject public BillingService(ICreditCardProcessor creditCardProcessor, ITransactionLog transactionLog) { fCreditCardProcessor = creditCardProcessor; fTransactionLog = transactionLog; }

public Receipt chargeOrder(Order order, CreditCard creditCard) { ... }}

Page 33: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

33 Dependency InjectionSandro Pedrazzini

• Injectable properties: non è necessario prevedere il costruttore per l’inizializzazione

DI con Guice (5)

public class BillingService implements IBillingService { @Inject private ICreditCardProcessor fCreditCardProcessor; @Inject private ITransactionLog fTransactionLog;

public Receipt chargeOrder(Order order, CreditCard creditCard) { ... }}

Page 34: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

34 Dependency InjectionSandro Pedrazzini

Utilizzo

public static void main(String[] args) {

Injector injector = Guice.createInjector(new BillingModule());

//ricevel’oggetto top level IBillingService billingService = injector.getInstance(IBillingService.class);

Receipt receipt = billingService.chargeOrder( new PizzaOrder(100), new CreditCard("1234", 6, 2012));

if (receipt.hasSuccessfulCharge()) { System.out.println("Receipt value: " + receipt.getAmountOfCharge()); } else { System.out.println("Receipt value: " + receipt.getErrorMessage()); } }

Page 35: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

35 Dependency InjectionSandro Pedrazzini

Altri punti di injection (2)

• Anche un metodo può essere segnalato con @Inject. • Guice chiama questo metodo con l’oggetto associato subito

dopo aver chiamato il costruttore• Non dev’essere necessariamente un metodo set(), può avere

più parametri e non dev’essere per forza pubblico

@Injectpublic void setTransactionLog(ITransactionLog transactionLog){ fTransactionLog = transactionLog;}

Page 36: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

36 Dependency InjectionSandro Pedrazzini

Utilizzo di Guice per test (1)

public class TestModule extends AbstractModule { protected void configure() { bind(ITransactionLog.class).to(InMemoryTransactionLog.class); bind(ICreditCardProcessor.class).to(FakeCreditCardProcessor.class);

bind(IBillingService.class).to(BillingService.class); }}

Page 37: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

37 Dependency InjectionSandro Pedrazzini

Utilizzo di Guice per test (2)

public class BillingServiceWithGuiceTest {

private Injector injector = Guice.createInjector(new TestModule());

@Test public void testSuccessfulCharge() { Order order = new PizzaOrder(100); CreditCard creditCard = new CreditCard("1234", 11, 2010);

IBillingService billingService = injector.getInstance(IBillingService.class);

Receipt receipt = billingService.chargeOrder(order, creditCard);

assertTrue(receipt.hasSuccessfulCharge()); assertEquals(100, receipt.getAmountOfCharge()); assertTrue(billingService.getTransactionLog().successfullyLogged()); }}

Page 38: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

38 Dependency InjectionSandro Pedrazzini

Provider

• Capita che per la creazione di un oggetto sia necessario più codice che la semplice chiamata al costruttore

• Normalmente in questi casi scriveremmo un metodo factory, che contenga la chiamata al costruttore, più il codice necessario

• In Guice il metodo factory viene specificato nel modulo di binding e viene chiamato @Provides method, dal nome dell’annotation da applicare

• Il binding in configure() va tolto

Page 39: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

39 Dependency InjectionSandro Pedrazzini

Metodo @Provides

public class BillingModule extends AbstractModule { protected void configure() { // bind(ITransactionLog.class).to(DatabaseTransactionLog.class); ... }

@Provides  ITransactionLog provideTransactionLog() {    DatabaseTransactionLog transactionLog = new DatabaseTransactionLog();    transactionLog.setJdbcUrl("jdbc:mysql://localhost/trans");   transactionLog.setThreadPoolSize(30);

  return transactionLog;  }}

Page 40: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

40 Dependency InjectionSandro Pedrazzini

Classe Provider

• Quando un metodo @Provides inizia ad essere troppo complesso, si può pensare di creare una classe Provider dedicata

• Guice prevede a questo scopo un’interfaccia Provider che va implementata

public interface Provider<T> { T get(); }

Page 41: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

41 Dependency InjectionSandro Pedrazzini

Classe Provider (2)

public class DBTransactionProvider implements Provider<ITransactionLog> {

public ITransactionLog get() { DatabaseTransactionLog transactionLog = new DatabaseTransactionLog(); transactionLog.setJdbcUrl("jdbc:mysql://localhost/trans");   transactionLog.setThreadPoolSize(30);

return transactionLog; }}

Classe responsabile della creazione dell’oggetto ITransactionLog

Page 42: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

42 Dependency InjectionSandro Pedrazzini

Classe Provider (3)

• Binding nella classe di modulo

public class BillingModule extends AbstractModule { protected void configure() { bind(ITransactionLog.class). toProvider(DBTransactionProvider.class); ... }

...}

Page 43: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

43 Dependency InjectionSandro Pedrazzini

Request Injector

• Necessario quando all’interno di configure si deve instanziare un oggetto da usare in modo particolare: si crea e si forza il passaggio delle dipendenze ai campi @Inject

public class BillingModule extends AbstractModule {

protected void configure() { bind(ITransactionLog.class).to(DatabaseTransactionLog.class); bind(ICreditCardProcessor.class).to(PaypalCreditCardProcessor.class);

IBillingService billingService = new BillingService(); //necessario forzare injection requestInjection(billingService); … }

Page 44: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

44 Dependency InjectionSandro Pedrazzini

Utilizzo contemporaneo di più moduli

• Più moduli possono essere usati contemporaneamente, se è necessario usare oggetti della stessa classe, ma inizializzati diversamente

• L’utilizzo di più moduli può essere utile anche a cascata: se un oggetto di un modulo dev’essere creato manualmente all’interno di un provider, se ha dipendenze, queste potrebbero essere specificate all’interno di un secondo modulo.

Page 45: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

45 Dependency InjectionSandro Pedrazzini

Utilizzo contemporaneo di più moduli (2)

public class DBTransactionProvider implements Provider<ITransactionLog> {

public ITransactionLog get() { Injector injector = Guice.createInjector(new DBProductionModule());

ITransactionLog transactionLog = injector.getInstance(ITransactionLog.class); …

return transactionLog; }}

Page 46: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

46 Dependency InjectionSandro Pedrazzini

Scope

• Per default, Guice restituisce una nuova istanza ogni volta che un oggetto viene richiesto

• Esempio

– Ogni colta che si richiede un oggetto ITransactionLog a questo modulo, viene creata una nuova istanza di InMemoryTransactionLog

bind(ITransactionLog.class). to(InMemoryTransactionLog.class);

Page 47: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

47 Dependency InjectionSandro Pedrazzini

Scope (2)

• Esistono altri scope, a scelta:– per l’intero ciclo di vita dell’applicazione (@Singleton)– per la durata di una sessione (@SessionScoped)– per una singola richiesta (@RequestScoped)

• Esempio– Scope configurato durante il binding:

bind(ITransactionLog.class). to(InMemoryTransactionLog.class). in(Singleton.class);

Page 48: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

48 Dependency InjectionSandro Pedrazzini

Scope (3)

• Eager singleton

– Guice prevede la possibilità di specificare oggetti singleton da costruire subito, in anticipo (eagerly)

bind(ITransactionLog.class). to(InMemoryTransactionLog.class). asEagerSingleton();

Page 49: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

49 Dependency InjectionSandro Pedrazzini

DI con Spring

• Il Bean Container di Spring risolve le dipendenze durante il caricamento dei singoli oggetti

• Le dipendenze vengono specificate in un file di configurazione

• Le dipendenze possono essere specificate, con l’annotation @Autowired

• Le dipendenze possono essere passate via costruttore o via metodi “set”

Page 50: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

50 Dependency InjectionSandro Pedrazzini

Definizione di Bean

• Le definizioni dei Bean all’interno di una variante di BeanFactory sono rappresentate con oggetti BeanDefinition, contenenti almeno (anche solo implicitamente):– nome o id– nome della classe– elementi di configurazione del comportamento (prototype o singleton,

inizializzazione, etc.)– argomenti di costruttore e property values da assegnare al bean creato– altri bean necessari al bean considerato per eseguire il suo lavoro

(dipendenze)

<bean id="exampleBean” class="examples.ExampleBean"/>

Page 51: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

51 Dependency InjectionSandro Pedrazzini

Singleton

• I Bean sono definiti per essere installati e attivati in due modalità: singleton o non-singleton (prototype)

• Altre modalità sono disponibili per ApplicationContext di applicazioni Web (request, session, global session (portlet))

• Quando un bean è un singleton, un’unica instanza (shared) del bean viene gestita e creata (per bean e container)

• Per default i bean sono attivati in modalità singleton

Page 52: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

52 Dependency InjectionSandro Pedrazzini

Singleton vs. Prototype

Singleton (per bean e contesto)

Page 53: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

53 Dependency InjectionSandro Pedrazzini

Singleton vs. Prototype

• Prototype (istanza)

Page 54: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

54 Dependency InjectionSandro Pedrazzini

Proprietà e Dipendenze

• Le dipendenze possono essere specificate con costruttore o con metodi set

<bean id="exampleBean" class="examples.ExampleBean"> <property name="beanOne” ref="anotherExampleBean"/></property> <property name="beanTwo” ref="yetAnotherBean"/></property> <property name="integerProperty"><value>1</value></property></bean>

<bean id="anotherExampleBean" class="examples.AnotherBean"/>

<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>

Page 55: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

55 Dependency InjectionSandro Pedrazzini

Spring DI (3)

public class ExampleBean { private AnotherBean fBeanOne; private YetAnotherBean fBeanTwo; private int fValue;

public void setBeanOne(AnotherBean beanOne) { fBeanOne = beanOne; } public void setBeanTwo(YetAnotherBean beanTwo) { fBeanTwo = beanTwo; } public void setIntegerProperty(int value) { fValue = value; }}

<bean id="exampleBean" class="examples.ExampleBean"> <property name="beanOne” ref=.../></property> <property name="beanTwo” ref=.../></property> <property name="integerProperty"> <value>1</value> </property></bean>

Esempio

Page 56: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

56 Dependency InjectionSandro Pedrazzini

BillingService con Spring

• Specificare metodi set per RealBillingService

public class BillingService implements IBillingService { private ICreditCardProcessor fCreditCardProcessor; private ITransactionLog fTransactionLog;

...

public void setCreditCardProcessor(ICreditCardProcessor processor) { fCreditCardProcessor = processor; }

public void setTransactionLog(ITransactionLog transactionLog) { fTransactionLog = transactionLog; }

...}

Page 57: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

57 Dependency InjectionSandro Pedrazzini

BillingService con Spring (2)

<bean id=”billingServiceBean" class="examples.BillingService> <property name=”creditCardProcessor” ref="creditCardProcessor"/> <property name=”transactionLog” ref="transactionLog"/></bean>

<bean id=”creditCardProcessor" class="examples.PaypalCrediCardProcessor”/>

<bean id=”transactionLog" class="examples.DatabaseTransactionLog”/>

Page 58: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

58 Dependency InjectionSandro Pedrazzini

Confronto: Guice e Spring

• Spring rappresenta un intero stack di elementi per applicazioni enterprise, di cui DI è un tassello

• Si può comunque usare Spring anche solo per DI (Spring non è un framework “all or nothing”)

• Guice si concentra invece puramente sugli aspetti di DI (e AOP)

Page 59: 1 Dependency Injection Sandro Pedrazzini Approfondimento Dependency Injection

59 Dependency InjectionSandro Pedrazzini

Confronto: Guice e Spring (2)

• La configurazione Spring (esplicita) avviene in XML, quindi scomoda e poco concisa (tool di sviluppo che offrono una buona integrazione tra Java e XML aiutano comunque a rendere mantenibili le applicazioni)

• Esiste in Spring una modalità di configurazione “autowired”

• Guice utilizza annotations, una buona via di mezzo: una modalità concisa, esplicita, mantenibile e supportata dal linguaggio di programmazione