Google Guice é o framework para automatizar a injeção de dependência em aplicações. Se você chegou diretamente aqui, recomendaria que você confira 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 trabalho principal é 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 Maven Central, 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, então 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, ou então ocorrerá uma exceção em tempo de execução. Para o meu exemplo, tenho um projeto Maven cuja estrutura do projeto 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);
}
A interface MessageService
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 injetoras, essa anotação é fornecida para informá-las de que as classes de serviço devem ser objetos singleton. O Google Guice 3.0 adicionou o 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 baseada em setter
e construtor
. Nossa classe de aplicativo que consome o serviço parece assim.
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);
}
}
Aviso que eu comentei o código para injeção baseada no construtor, isso é útil quando sua aplicação fornece outras funcionalidades que não precisam de um objeto da classe de serviço. Observe também a @Injector anotação, esta será usada 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.
Vinculação da 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 de Mensagem do Facebook
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 de injetor. Em seguida, 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
, 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 de serviço real. Podemos ter uma classe de implementação de serviço simples de simulação 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 com a seguinte.
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]"));;
}
}
Repare que estou vinculando a classe MockMessageService
à MessageService
através de uma implementação de classe anônima da 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 um aplicativo é muito fácil e ele o faz de forma elegante. Ele é utilizado nas APIs do Google, então podemos assumir que é um código altamente testado e confiável. Baixe o projeto acima e explore-o para aprender mais.
Source:
https://www.digitalocean.com/community/tutorials/google-guice-dependency-injection-example-tutorial