7 votes

Guice/Gin. Comment injecter des implémentations multiples

J'ai une application web qui utilise GIN pour injecter les dépendances au point d'entrée.

private InjectorService injector = GWT.create(InjectorService.class);

@GinModules({PlaceContollerInject.class, RootViewInject.class})
public interface InjectorService extends Ginjector {

  RootView getRootView();
  PlaceController getPlaceConroller();

}

public class RootViewInject extends AbstractGinModule {

  @Override
  protected void configure() {
    bind(RootView.class).to(RootViewImpl.class);
  }
}

J'ai besoin d'une version mobile qui utilise une implémentation différente de RootView. Les dépendances sont décrites dans le module suivant

public class RootViewMobileInject extends AbstractGinModule {

  @Override
  protected void configure() {
    bind(RootView.class).to(RootViewMobileImpl.class);
  }
}

La question est de savoir comment choisir la dépendance nécessaire en fonction de la version mobile ou par défaut. J'ai vu Implémentations multiples de GWT-GIN mais je n'ai pas encore trouvé de solution parce que le fournisseur brise la chaîne des dépendances et le modèle d'usine brise la testabilité. Dans la vidéo "Big Modular Java with Guice" (en anglais) ici (12 minutes) L'injecteur de modules de Guice a été présenté comme un remplacement des Factories. Ma question est donc de savoir si je dois créer des Ginjector différents pour les versions mobiles et par défaut (comme MobileFactory et DefaultFactory) de mon application ou si ce serait une mauvaise pratique et que je devrais configurer une instance de Ginjector avec toutes les versions nécessaires. Par exemple, avec les liaisons d'annotation comme ceci.

public class RootViewMobileInject extends AbstractGinModule {

  @Override
  protected void configure() {
    bind(RootView.class).annotatedWith(Mobile.class).to(RootViewMobileImpl.class);
  }
}

et utiliser les liaisons annotées @Mobile au point d'entrée de GWT

  @Inject
  private void setMobileRootView(@Mobile RootView rw) {
    this.rw = rw;
  }

Dans un exemple aussi simplifié que celui qui précède, cela pourrait être possible. Mais si une application a plus de dépendances qui nécessitent des versions mobiles et par défaut. Il semble que l'on revienne à des usines "laides" et non testables (comme on l'a dit lors de la présentation de Guice). Désolé pour mon anglais. Toute aide est appréciée.

9voto

aidanok Points 849

Je pense que vous voudrez utiliser la liaison différée GWT, en utilisant le remplacement de classe pour lier une version différente de votre InjectorService en fonction de l'agent utilisateur. Cela garantira que la version mobile n'a que les implémentations mobiles compilées (et téléchargées).

Ainsi, vous auriez InjectorServiceDesktop, InjectorServiceMobile, qui s'étendent tous deux à partir de InjectorService, puis GWT.create(InjectorService.class), et laisser la liaison différée décider de l'implémentation à utiliser.

http://code.google.com/webtoolkit/doc/latest/DevGuideCodingBasicsDeferred.html#replacement

Une seule instance de Ginjector avec toutes les versions semble mauvaise car cela signifie que tout le code des deux versions est toujours téléchargé (et vous ne voulez certainement pas télécharger toutes vos vues de bureau dans votre application mobile).

EDIT : Comme Thomas le souligne dans les commentaires, puisque les Injectors sont des classes générées, vous devrez mettre chaque InjectorServiceXXX à l'intérieur d'une simple classe porteuse qui GWT.create()'s l'InjectorServiceXXX, et utiliser le remplacement pour passer d'un support à l'autre.

1voto

99Sono Points 141

Faire ce que vous voulez est en fait assez compliqué car votre interface d'injecteur commune, qui est annotée avec votre module Gin, ne peut pas pointer vers un module Gin abstrait. Le module Gin pointé par votre interface Ginjector doit être un module concret. Un module concret ne peut pas satisfaire plusieurs configurations en même temps.

Donc ce que tu fais c'est : (a) Créer votre interface Ginjector, disons ClientGinjector et votre Module, ClientModule, pour une application de bureau.

(b) Créez une deuxième interface Ginjector, disons ClientGinjectorTablet, étendant celle que vous avez créée en (a) mais avec une annotation GinModule pointant vers un Module différent, disons ClientModuletablet.

-- Maintenant vous avez deux interfaces Ginjecor, une par défaut et une secondaire pour les tablettes, chacune pointant vers un module avec ses propres implémentations de Configure().

(c) Maintenant, vous voulez créer Factory pour obtenir votre implémentation de Right Ginjector. Vous pouvez le faire parce que le Ginjector que vous avez soigné dans (a) et (b) ont un démonitador commun qui est l'interface par défaut créée dans (a). Vous créez donc une interface abstraite avec une méthode telle que celle-ci : public abstract ClientGinjector getInjector() ; Vous créez deux classes concrètes enfants Une pour obtenir le Ginjector Desktop/Default et une autre pour obtenir le Ginjector Tablet.

(d) Maintenant vous configurez le gwt.xml de votre module comme Google IO sur youtube explique que vous devriez faire pour obtenir votre facotry désiré pendant l'exécution, en utilisant des liaisons différées GWT pour chacune de vos usines Ginjector.

(e) Sur votre point d'entrée, la première chose à faire n'est pas d'obtenir un Ginjector mais votre usine pour les Ginjectors en utilisant la liaison différée GWT. Vous appelez la méthode abstraite qui retourne un ClientGinjector, votre ensemble.

(f) L'échec épique à la fin. Guice ne vous permet pas de lier deux fois la même clé (classe plus annotation), même si vous utilisez des injecteurs différents (un pour le bureau et un pour la tablette). Il semble que les définitions des clés sont globales, dès que vous avez deux modules qui redéfinissent les mêmes clés, c'est la fin de l'aventure.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X