Esempio tutorial sull’iniezione di dipendenza Google Guice

Google Guice è il framework per automatizzare l’iniezione delle dipendenze nelle applicazioni. Se sei arrivato direttamente qui, ti consiglierei di dare un’occhiata all’Esempio di Iniezione delle Dipendenze dove abbiamo appreso i problemi dell’approccio tradizionale alla creazione degli oggetti e i vantaggi dell’implementazione dell’iniezione delle dipendenze. Nel tutorial precedente, abbiamo appreso come implementare manualmente l’iniezione delle dipendenze nelle applicazioni. Ma quando il numero di classi aumenta in un’applicazione, è meglio cercare un framework per automatizzare questo compito. Google Guice è uno dei principali framework il cui lavoro principale è fornire l’implementazione automatica dell’iniezione delle dipendenze. Lavoreremo sullo stesso esempio dell’ultimo post e impareremo come possiamo utilizzare Google Guice per automatizzare il processo di implementazione dell’iniezione delle dipendenze. Le dipendenze di Google Guice sono disponibili su maven central, quindi per progetti maven puoi aggiungere la dipendenza sottostante per essa.

<dependency>
	<groupId>com.google.inject</groupId>
	<artifactId>guice</artifactId>
	<version>3.0</version>
</dependency>

Se hai un’applicazione Java semplice, puoi scaricare il file jar dalla Pagina Principale di Google Guice su Google Code. Nota che in questo caso avrai anche bisogno delle sue dipendenze trasversali nel classpath, altrimenti otterrai un’eccezione durante l’esecuzione. Per il mio esempio, ho un progetto maven la cui struttura del progetto è simile all’immagine sottostante. Vediamo ciascuno dei componenti uno per uno.

Classi di servizio

package com.journaldev.di.services;

public interface MessageService {

	boolean sendMessage(String msg, String receipient);
}

L’interfaccia MessageService fornisce il contratto di base per i servizi.

package com.journaldev.di.services;

import javax.inject.Singleton;

//import com.google.inject.Singleton;

@Singleton
public class EmailService implements MessageService {

	public boolean sendMessage(String msg, String receipient) {
		//qualche codice fantasioso per inviare email
		System.out.println("Email Message sent to "+receipient+" with message="+msg);
		return true;
	}

}

EmailService è una delle implementazioni di MessageService. Nota che la classe è annotata con l’annotazione @Singleton. Poiché gli oggetti di servizio verranno creati attraverso classi di iniezione, questa annotazione è fornita per far sapere loro che le classi di servizio dovrebbero essere oggetti singleton. Google Guice 3.0 ha aggiunto il supporto per JSR-330 e possiamo utilizzare annotazioni dal pacchetto com.google.inject o javax.inject. Diciamo che abbiamo un’altra implementazione del servizio per inviare messaggi su Facebook.

package com.journaldev.di.services;

import javax.inject.Singleton;

//import com.google.inject.Singleton;

@Singleton
public class FacebookService implements MessageService {

	public boolean sendMessage(String msg, String receipient) {
		//alcun codice complesso per inviare messaggi su Facebook
		System.out.println("Message sent to Facebook user "+receipient+" with message="+msg);
		return true;
	}

}

Classe Consumatore

Dato che stiamo implementando l’iniezione delle dipendenze nella nostra applicazione, non inizializzeremo la classe di servizio nell’applicazione. Google Guice supporta sia l’iniezione delle dipendenze basata su setter che su costruttore. La nostra classe di applicazione che consuma il servizio appare come segue.

package com.journaldev.di.consumer;

import javax.inject.Inject;

//import com.google.inject.Inject;
import com.journaldev.di.services.MessageService;

public class MyApplication {

	private MessageService service;
	
// costruttore basato sull'iniettore
// @Inject
// pubblico MyApplication(MessageService svc){
//		this.service=svc;
//	}
	
	// iniettore basato sul metodo setter
	@Inject
	public void setService(MessageService svc){
		this.service=svc;
	}
	
	public boolean sendMessage(String msg, String rec){
		// qualche logica aziendale qui
		return service.sendMessage(msg, rec);
	}
}

Si noti che ho commentato il codice per l’iniezione basata sul costruttore, questo è utile quando l’applicazione fornisce anche altre funzionalità che non richiedono l’oggetto della classe di servizio. Si noti anche l’annotazione @Injector, questa sarà utilizzata da Google Guice per iniettare la classe di implementazione del servizio. Se non si è familiari con le annotazioni, controllare il tutorial sulle annotazioni in Java.

Configurazione dell’implementazione del servizio

Ovviamente google guice non saprà quale servizio utilizzare, dobbiamo configurarlo estendendo AbstractModule classe astratta e fornire l’implementazione per il metodo configure().

package com.journaldev.di.injector;

import com.google.inject.AbstractModule;
import com.journaldev.di.services.EmailService;
import com.journaldev.di.services.FacebookService;
import com.journaldev.di.services.MessageService;

public class AppInjector extends AbstractModule {

	@Override
	protected void configure() {
		// collegare il servizio alla classe di implementazione
		//bind(MessageService.class).to(EmailService.class);
		
		// collegare MessageService all'implementazione del messaggio di Facebook
		bind(MessageService.class).to(FacebookService.class);
		
	}

}

Come puoi vedere, possiamo associare qualsiasi implementazione alla classe di servizio. Ad esempio, se vogliamo passare a EmailService, dovremmo solo cambiare i binding.

Applicazione Client

La nostra configurazione è pronta, vediamo come usarla con una semplice classe Java.

package com.journaldev.di.test;

import com.google.inject.Guice;
import com.google.inject.Injector;

import com.journaldev.di.consumer.MyApplication;
import com.journaldev.di.injector.AppInjector;

public class ClientApplication {

	public static void main(String[] args) {
		Injector injector = Guice.createInjector(new AppInjector());		
		
		MyApplication app = injector.getInstance(MyApplication.class);
		
		app.sendMessage("Hi Pankaj", "[email protected]");
	}

}

L’implementazione è molto facile da capire. Dobbiamo creare l’oggetto Injector utilizzando il metodo createInjector() della classe Guice, dove passiamo l’oggetto di implementazione della nostra classe di iniezione. Quindi utilizziamo l’injector per inizializzare la nostra classe consumer. Se eseguiamo la classe sopra, produrrà il seguente output.

Message sent to Facebook user [email protected] with message=Hi Pankaj

Se cambiamo i binding a EmailService nella classe AppInjector, produrrà il seguente output.

Email Message sent to [email protected] with message=Hi Pankaj

Casi di Test JUnit

Dato che vogliamo testare la classe MyApplication, non è necessario creare un’implementazione effettiva del servizio. Possiamo avere una semplice classe di implementazione del servizio fittizia come segue.

package com.journaldev.di.services;

public class MockMessageService implements MessageService{

	public boolean sendMessage(String msg, String receipient) {
		return true;
	}

}

La mia classe di test JUnit 4 appare come segue.

package com.journaldev.di.test;


import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.journaldev.di.consumer.MyApplication;
import com.journaldev.di.services.MessageService;
import com.journaldev.di.services.MockMessageService;

public class MyApplicationTest {

	private Injector injector;
	
	@Before
	public void setUp() throws Exception {
		injector = Guice.createInjector(new AbstractModule() {
			
			@Override
			protected void configure() {
				bind(MessageService.class).to(MockMessageService.class);
			}
		});
	}

	@After
	public void tearDown() throws Exception {
		injector = null;
	}

	@Test
	public void test() {
		MyApplication appTest = injector.getInstance(MyApplication.class);
		Assert.assertEquals(true, appTest.sendMessage("Hi Pankaj", "[email protected]"));;
	}

}

Nota che sto associando la classe MockMessageService a MessageService attraverso un’implementazione anonima della classe AbstractModule. Questo viene fatto nel metodo setUp(), che viene eseguito prima dei metodi di test.

Scarica il progetto Google Guice

Questo è tutto per il Tutorial di Esempio di Google Guice. L’utilizzo di Google Guice per implementare l’iniezione delle dipendenze nell’applicazione è molto semplice e lo fa in modo eccellente. È utilizzato nelle API di Google, quindi possiamo presumere che si tratti di un codice ampiamente testato e affidabile. Scarica il progetto da sopra e sperimenta con esso per apprendere di più.

Source:
https://www.digitalocean.com/community/tutorials/google-guice-dependency-injection-example-tutorial