Google Guice, injecteur de dépendance

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 ()); } };);
     }
});
 

Ce sujet vous intéresse ?

NOUS CONTACTER