Le but d’un injecteur de dépendance est d’avoir accès à des objets, sans se préoccuper de leur instantiation. Comment et quand les instancier ? Comment y faire référence ? Voilà des problématiques que Google Guice saura répondre à votre place.

Trois étapes sont importantes pour son utilisation :

  • Déclarer son « listener » (point d’entrée de l’application) dans web.xml qui étend de GuiceServletContextListener
  • Déclarer vos dépendances dans le « listener » via des modules
  • Accèder à vos dépendances depuis n’importe où grâce à une simple annotation d’injection (dans vos constructeurs, vos méthodes, vos propriétés, …)

Dans Guice, une dépendance peut être :

  • Une classe (un service « singleton »)
  • Une instance de classe
  • Une constante
  • Un Provider (on peut voir ça comme un getter d’objet dépendant du contexte au moment où il est appelé, comme un objet en session)

Un des avantages à déclarer ses dépendances (services et autres) en Java plutôt qu’en XML (Spring) est de maîtriser ce qu’on injecte en fonction du contexte d’exécution. Typiquement :

  • Pour les tests unitaires, démarrer facilement le ou les services testés seulement
  • Toujours pour les tests unitaires, injecter une autre instance à une dépendance, avec un mock ou une implémentation plus « light » d’un service
  • Pour vos différents environnements (integration / production et client / fournisseur), mocker les applications tierces très facilement
  • Pour vos projets modulaires, peut importe ce qu’on injecte et où on le fait, accéder simplement à votre dépendance

Guice vous permet aussi de déclarer les filtres et Web Services de votre webapp en Java. Là aussi, l’intérêt est de pouvoir manipuler librement vos déclarations.

Enfin, une autre bonne raison d’adopter ce framework : Son éditeur 🙂 Tout de même réputé pour ses développements légers, fiables et efficaces !

Quelques exemples d’utilisation :

1. Déclaration des dépendances dans un « Module »

import com. google.inject .AbstractModule;
import com. google.inject .Scopes;
 
public class MyModule extends AbstractModule {
 @Override
   protected void configure() {
  
   // Déclaration d’une implémentation
 bind(MyService.class).to (MyServiceServiceImpl.class).in (Scopes. SINGLETON);
   // Utilisation : @Inject MyService service;
  
   // Déclaration d’une instance
 bind (MyClass.class).toInstance (MyClassFactory.get());
   // Utilisation : @Inject MyClass obj;
  
   // Déclaration d’une variable
 bind (String. class).annotatedWith (Names. named(« MY_CONSTANT_ANNOTATION » )).to( « value »);
   // Utilisation : @Inject @Named(« MY_CONSTANT_ANNOTATION ») String var;
  
   // Déclaration d’une constante
 bindConstant ().annotatedWith(Names.named (« MY_CONSTANT_ANNOTATION »)).to(« value » );
   // Utilisation : @Inject @Named(« MY_CONSTANT_ANNOTATION ») String var;
  
   // Déclaration multiple
 Multibinder <MyClass> setObj = Multibinder .newSetBinder(binder(), MyClass.class);
 setObj .addBinding().toInstance(new MyClass(« param » ));
 setObj .addBinding().toInstance(new MyClass(« otherParam » ));
   // Utilisation : @Inject Set<MyClass> setObj;
   }

2. Déclaration des Modules

import com. google.inject .Guice;
import com. google.inject .Injector;
import com. google.inject .servlet.GuiceServletContextListener;
 
public abstract class MyContextListener extends GuiceServletContextListener {
 @Override
   protected Injector getInjector () {
   return Guice. createInjector(module1 , module2, …);
   }
  
}
 
Remarque :
Dans vos tests unitaires, il faut faire ce même travail de création de de « Injector » en déclarant seulement les modules nécessaires pour vos tests (D’où l’intérêt de na pas tout déclarer dans un seul module).
Et c’est la méthode « configure » de votre module qu’il faut surcharger si vous souhaitez injecter d’autres implémentations (Mock).

3. Utilisation de Jersey dans Guice (Implémenation de JAX-RS (JSR 311) pour WebServices RESTful)

3.1 Liste des webServices dans un objet « Application »

import javax. ws .rs .core . Application ;
 
public class MyListsServlets extends Application {
 @Override
  public Set < Class<?>> getClasses () {
  return ImmutableSet .of (
 MyFirstServlet . class,
 OtherWebService . class);
  }
}

3.2 Déclaration des WebServices dans un « ServletModule »

 
import com. google .inject . AbstractModule ;
import com. google .inject . servlet .ServletModule ;
import com. sun .jersey . guice. spi .container . servlet .GuiceContainer ;
 
AbstractModule moduleWS = new ServletModule () {
 @Override
   protected void configureServlets () {
 serve ( « /rest/* » ).with (GuiceContainer . class, new HashMap <String , String>() { { put (« javax.ws.rs.Application » , MyListsServlets. class .getName ()); } };);
   }
});