• [^] # Re: Injection de dépendance

    Posté par (site web personnel) . En réponse au journal De tout, de rien, des liens, du vrac (mais moins bookmarks cette fois). Évalué à 3.

    Ha mais j'ai quand même l'impression qu'il y a une grosse différence.
    Dans ton cas tout est fait par annotation des classes / membres.

    Dans Guice c'est possible avec @ImplementedBy et @ProvidedBy si j'ai bien compris ce que fait spring (voir http://code.google.com/p/google-guice/wiki/JustInTimeBindings)

    Mais c'est une énorme différence avec la ligne que j'ai citée.
    Le truc c'est que je peux très bien avoir un code, une lib, qui contient différents modules. Avec chacun des injections différentes. A mon code appelant de charger le bon module.
    Je peux également avoir des injections "paramétrées" avec @Named par exemple (http://code.google.com/p/google-guice/wiki/BindingAnnotations). Et également de l'injection d'instances (http://code.google.com/p/google-guice/wiki/InstanceBindings).

    Pour prendre un exemple réel. Voici la partie "lib" de mon code (bon ok, c'est pas purement réel mais c'est basé sur du réel) :

    // Bind de l'interface Searches vers une implémentation directe (pas de cache des résultats)
    bind(Searches.class).annotatedWith(Names.named("nocache")).to(SearchesNoCache.class);
    // Bind de mon cache loader (guava) pour injection
    bind(SearchesCacheLoader.class);
    // Bind de l'interface Searches vers une implémentation utilisant le cache loader
    bind(Searches.class).annotatedWith(Names.named("cache")).to(SearchesCache.class);
    
    

    Dans mon code appelant, je peux injecter Searches et en l'annotant différement j'aurai l'une ou l'autre des implémentations.

    @Inject
    @Named("nocache")
    private Searches searches;
    // ou
    @Inject
    @Named("cache")
    private Searches searches;
    
    

    Et pour aller plus loin, je peux très bien avoir le fonctionnement suivant. Dans ma lib, j'ai deux modules différents :

    Module nocache = new AbstractModule() {
     @Override
     protected void configure() {
     bind(Searches.class).to(SearchesNoCache.class);
     }
    };
    Module cache = new AbstractModule() {
     @Override
     protected void configure() {
     bind(Searches.class).annotatedWith(Names.named("nocache"))to(SearchesNoCache.class);
     bind(SearchesCacheLoader.class);
     bind(Searches.class).to(SearchesCache.class);
     }
    };
    
    

    Dans ce cas, il me suffit de choisir le bon module lors de la création de l'injecteur. Le truc c'est que la config peut être un paramètre, une variable système, une constante ou propriété au build, etc.
    Et donc je fais mes profiles facilement en ayant un seul code de base mais un comportement totalement différent.

    Injector injector = Guice.createInjector(needcache ? cache : nocache);
    // ok, tant qu'à faire ce ne sera pas des variables mais on colle un new ici, ça sert à rien
    // d'instancier à l'avance, mais c'est juste pour que l'exemple soit facile
    
    

    (si je suis pas clair, n'hésite pas. Et si spring le permet ça m'intéresse quand même)