Google Guice est le framework permettant d’automatiser l’injection de dépendances dans les applications. Si vous êtes arrivé directement ici, je vous recommande de consulter l’exemple d’injection de dépendances où nous avons étudié les problèmes avec l’approche traditionnelle de la création d’objets et les avantages de la mise en œuvre de l’injection de dépendances. Dans le dernier tutoriel, nous avons appris comment implémenter manuellement l’injection de dépendances dans les applications. Mais lorsque le nombre de classes augmente dans une application, il est préférable de rechercher un framework pour automatiser cette tâche. Google Guice est l’un des principaux frameworks dont le travail principal est de fournir une implémentation automatique de l’injection de dépendances. Nous travaillerons sur le même exemple que dans le dernier billet et apprendrons comment utiliser Google Guice pour automatiser le processus d’implémentation de l’injection de dépendances. Les dépendances de Google Guice sont disponibles sur Maven Central, donc pour les projets Maven, vous pouvez ajouter la dépendance suivante.
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>3.0</version>
</dependency>
Si vous avez une application Java simple, vous pouvez télécharger le fichier JAR depuis la page d’accueil de Google Guice sur Google Code. Notez que dans ce cas, vous devrez également avoir ses dépendances transitives dans le classpath, sinon vous obtiendrez une exception d’exécution. Pour mon exemple, j’ai un projet Maven dont la structure ressemble à l’image ci-dessous. Examions chacun des composants un par un.
Classes de service
package com.journaldev.di.services;
public interface MessageService {
boolean sendMessage(String msg, String receipient);
}
L'interface MessageService
fournit le contrat de base pour les services.
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) {
//quelques lignes de code sophistiquées pour envoyer un email
System.out.println("Email Message sent to "+receipient+" with message="+msg);
return true;
}
}
EmailService
est l’une des implémentations de MessageService
. Remarquez que la classe est annotée avec @Singleton. Étant donné que les objets de service seront créés via des classes injecteurs, cette annotation est fournie pour indiquer qu’elles doivent être des objets singleton. Google Guice 3.0 a ajouté la prise en charge de JSR-330 et nous pouvons utiliser des annotations à partir du package com.google.inject
ou javax.inject
. Supposons que nous ayons une autre implémentation de service pour envoyer des messages 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) {
//quelques lignes de code complexes pour envoyer un message Facebook
System.out.println("Message sent to Facebook user "+receipient+" with message="+msg);
return true;
}
}
Classe consommatrice
Comme nous mettons en œuvre l’injection de dépendances dans notre application, nous n’initialiserons pas la classe de service dans l’application. Google Guice prend en charge l’injection de dépendances basée sur les setters
et sur les constructeurs
. Notre classe d’application qui consomme le service ressemble à ce qui suit.
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);
}
}
Remarquez que j’ai commenté le code pour l’injection basée sur le constructeur, cela est pratique lorsque votre application propose également d’autres fonctionnalités qui n’ont pas besoin d’un objet de classe de service. Remarquez également l’annotation @Injecteur, celle-ci sera utilisée par Google Guice pour injecter la classe d’implémentation du service. Si vous n’êtes pas familier avec les annotations, consultez le tutoriel sur les annotations Java.
Configuration de l’implémentation du service
Évidemment, Google Guice ne saura pas quel service utiliser. Nous devons le configurer en étendant la AbstractModule
classe abstraite et en fournissant une implémentation de la méthode 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() {
// Lier le service à la classe d'implémentation
//bind(MessageService.class).to(EmailService.class);
// Lier MessageService à l'implémentation du message Facebook
bind(MessageService.class).to(FacebookService.class);
}
}
Comme vous pouvez le voir, nous pouvons lier n’importe quelle implémentation à la classe de service. Par exemple, si nous voulons passer à EmailService, il suffirait de modifier les liaisons.
Application Client
Notre configuration est prête, voyons comment l’utiliser avec une classe Java simple.
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’implémentation est très facile à comprendre. Nous devons créer un objet Injector
en utilisant la méthode createInjector() de la classe Guice, où nous passons l’objet de mise en œuvre de notre classe d’injecteur. Ensuite, nous utilisons l’injecteur pour initialiser notre classe consommateur. Si nous exécutons la classe ci-dessus, elle produira la sortie suivante.
Message sent to Facebook user [email protected] with message=Hi Pankaj
Si nous changeons les liaisons pour EmailService
dans la classe AppInjector
, cela produira la sortie suivante.
Email Message sent to [email protected] with message=Hi Pankaj
Cas de tests JUnit
Comme nous voulons tester la classe MyApplication, il n’est pas nécessaire de créer une implémentation de service réelle. Nous pouvons avoir une simple classe d’implémentation de service fictive comme ci-dessous.
package com.journaldev.di.services;
public class MockMessageService implements MessageService{
public boolean sendMessage(String msg, String receipient) {
return true;
}
}
Ma classe de test JUnit 4 ressemble à ceci.
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]"));;
}
}
Remarquez que je lie la classe MockMessageService
à MessageService
en ayant une implémentation de classe anonyme de AbstractModule
. Cela se fait dans la méthode setUp()
qui s’exécute avant les méthodes de test.
Téléchargez le projet Google Guice
C’est tout pour le tutoriel d’exemple Google Guice. L’utilisation de Google Guice pour implémenter l’injection de dépendances dans une application est très simple et elle le fait magnifiquement. Il est utilisé dans les API Google, donc nous pouvons supposer que c’est un code hautement testé et fiable. Téléchargez le projet ci-dessus et jouez avec pour en apprendre davantage.
Source:
https://www.digitalocean.com/community/tutorials/google-guice-dependency-injection-example-tutorial