Exemplo de Tutorial de Injeção de Dependência com Google Guice

Google Guice é o framework para automatizar a injeção de dependência em aplicações. Se você chegou diretamente aqui, eu recomendaria que você conferisse Exemplo de Injeção de Dependência, onde aprendemos sobre os problemas com a abordagem tradicional de criação de objetos e os benefícios da implementação da injeção de dependência. No último tutorial, aprendemos como podemos implementar a injeção de dependência manualmente em aplicações. Mas, quando o número de classes aumenta em uma aplicação, é melhor procurar por um framework para automatizar essa tarefa. O Google Guice é um dos principais frameworks cujo principal trabalho é fornecer a implementação automática da injeção de dependência. Vamos trabalhar no mesmo exemplo do último post e aprender como podemos usar o Google Guice para automatizar o processo de implementação da injeção de dependência. As dependências do Google Guice estão disponíveis no repositório central do Maven, então, para projetos Maven, você pode adicionar a seguinte dependência.

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

Se você tem uma aplicação Java simples, pode baixar o arquivo JAR na Página Inicial do Google Guice no Google Code. Note que, nesse caso, você também precisará ter as dependências transitivas no classpath, caso contrário, você receberá uma exceção em tempo de execução. Para o meu exemplo, tenho um projeto Maven cuja estrutura se parece com a imagem abaixo. Vamos ver cada um dos componentes um por um.

Classes de Serviço

package com.journaldev.di.services;

public interface MessageService {

	boolean sendMessage(String msg, String receipient);
}

MessageService interface fornece o contrato base para os serviços.

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) {
		//algum código sofisticado para enviar e-mail
		System.out.println("Email Message sent to "+receipient+" with message="+msg);
		return true;
	}

}

EmailService é uma das implementações de MessageService. Note que a classe é anotada com a anotação @Singleton. Como os objetos de serviço serão criados por meio de classes de injetor, esta anotação é fornecida para informar que as classes de serviço devem ser objetos singleton. O Google Guice 3.0 adicionou suporte para JSR-330 e podemos usar anotações do pacote com.google.inject ou javax.inject. Digamos que tenhamos outra implementação de serviço para enviar mensagens no 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) {
		//algum código complexo para enviar mensagem no Facebook
		System.out.println("Message sent to Facebook user "+receipient+" with message="+msg);
		return true;
	}

}

Classe Consumidora

Como estamos implementando injeção de dependência em nossa aplicação, não inicializaremos a classe de serviço na aplicação. O Google Guice suporta injeção de dependência tanto baseada em setter quanto em construtor. Nossa classe de aplicação que consome o serviço se parece com abaixo.

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;
	
//	constructor based injector
//	@Inject
//	public MyApplication(MessageService svc){
//		this.service=svc;
//	}
	
	//setter method injector
	@Inject
	public void setService(MessageService svc){
		this.service=svc;
	}
	
	public boolean sendMessage(String msg, String rec){
		//some business logic here
		return service.sendMessage(msg, rec);
	}
}

Observe que eu comentei o código para injeção baseada em construtor, isso é útil quando sua aplicação fornece outras funcionalidades que não precisam do objeto da classe de serviço. Também observe a @Injector anotação, isso será usado pelo Google Guice para injetar a classe de implementação do serviço. Se você não está familiarizado com anotações, confira o tutorial de anotações em Java.

Vinculando a Implementação do Serviço

Obviamente, o Google Guice não saberá qual serviço usar, precisamos configurá-lo estendendo a classe AbstractModule classe abstrata e fornecendo a implementação para o método 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() {
		//vincule o serviço à classe de implementação
		//bind(MessageService.class).to(EmailService.class);
		
		//vincule o MessageService à implementação do Facebook Message
		bind(MessageService.class).to(FacebookService.class);
		
	}

}

Como você pode ver, podemos vincular qualquer implementação à classe de serviço. Por exemplo, se quisermos mudar para EmailService, só precisaríamos alterar os vínculos.

Aplicação Cliente

Nossa configuração está pronta, vamos ver como usá-la com uma classe Java simples.

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]");
	}

}

A implementação é muito fácil de entender. Precisamos criar um objeto Injector usando o método createInjector() da classe Guice, onde passamos nosso objeto de implementação da classe Injector. Então usamos o injetor para inicializar nossa classe consumidora. Se executarmos a classe acima, ela produzirá a seguinte saída.

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

Se alterarmos os vínculos para EmailService na classe AppInjector, então produzirá a seguinte saída.

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

Casos de Teste JUnit

Como queremos testar a classe MyApplication, não precisamos criar uma implementação real do serviço. Podemos ter uma classe de implementação de serviço simples de mock, como abaixo.

package com.journaldev.di.services;

public class MockMessageService implements MessageService{

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

}

Minha classe de teste JUnit 4 parece assim.

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]"));;
	}

}

Observe que estou vinculando a classe MockMessageService à MessageService por meio de uma implementação de classe anônima de AbstractModule. Isso é feito no método setUp() que é executado antes dos métodos de teste.

Download do Projeto Google Guice

Isso é tudo para o Tutorial de Exemplo do Google Guice. O uso do Google Guice para implementar injeção de dependência em aplicativos é muito fácil e ele o faz de maneira excelente. Ele é usado nas APIs do Google, então podemos supor que é um código altamente testado e confiável. Baixe o projeto acima e brinque com ele para aprender mais.

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