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