2014-04-19 1 views
1

J'ai besoin d'aide pour utiliser guice. J'ai mon projet ici: https://github.com/Romain-P/kalibro/blob/master/realm/src/org/kalibro/core/Main.javaGoogle guice: aider à injecter

Mon problème: J'ai besoin de remplacer dans ce Main.java les 3 injecteurs, avec seulement 1 injecteur. L'application est séparée: LoginServer et WorldServers. Vous avez seulement 1 realmServer, et certains serveurs WorldServer comme vous le souhaitez.

Maintenant, je viens de créer realmServer. Dans ce que vous avez: - RealmManager (qui gère les joueurs < -> loginserver) - ExchangeManager (qui gère des mondes < -> loginserver)

Ils acceptent des connexions, et ils créent des clients, avec Netty. RealmManager & ExchangeManager étend NetworkService. NetworkService est une classe abstractClass, utile pour créer tous les gestionnaires comme vous le souhaitez. Imaginez si je veux plus tard créer shopManager, qui parle avec webServer.

S'il vous plaît voir le code: https://github.com/Romain-P/kalibro/tree/master/realm/src/org/kalibro/network/netty

Maintenant, mon Main.java a 3 injecteurs, mais je dois avoir juste 1. qui fonctionne! mais je pense que ce n'est pas nettoyé, donc j'ai juste besoin d'un injecteur.

Main.java

[...] 
Injector exchangeInjector = Guice.createInjector(new ExchangeModule()); 
Injector realmInjector = Guice.createInjector(new RealmModule()); 
try { 
    log.info("initializing exchange"); 
    exchangeInjector.getInstance(ExchangeManager.class).run(config.getExchangePort()); 
    log.info("initializing server"); 
    realmInjector.getInstance(RealmManager.class).run(config.getRealmPort()); 
} catch(Exception e) { 
    log.error("Can't start application", +e.getMessage()); 
    System.exit(1); 
} 

Modules:

public class RealmModule extends AbstractModule { 
    protected void configure() { 
     install(new NetworkModule()); 
     bind(NetworkService.class).to(RealmManager.class); 
    } 
} 
//the same for ExchangeModule.. 
+0

Avez-vous besoin de se lier à la fois à 'NetworkService'? Vous résolvez les instances en utilisant les classes concrètes - pouvez-vous vous contenter de simplement vous lier aux classes concrètes, par ex. 'bind (RealmManager.class);', dans le module? Ensuite, les deux modules peuvent être créés dans un seul injecteur. –

+0

modifier * attente s'il vous plaît –

+0

il est impossible, parce que je @Inject NETWORKSERVICE à networkServiceHandler, et il sera ne sais pas ce gestionnaire utiliser –

Répondre

3

injecteur Guice a ... tableau en tant qu'argument:

Guice.createInjector(Module... modules); 

Vous pouvez simplement faire:

Guice.createInjector(new ExchangeModule(), new RealmModule()); 

S'il y a des conflits, vous pouvez essayer binding annotations ou untargetted bindings.

EDIT:

Cela pourrait montrer comment vous pouvez éviter les conflits:

bind(NetworkService.class).annotatedWith(Exchange.class).to(ExchangeManager.class); 
bind(NetworkService.class).annotatedWith(Realm.class).to(RealmManager.class); 

alors:

@Inject 
@Exchange 
private NetworkService exchangeService; 

EDIT 2:

Je pense que le plus grand problème est la manière vous initiez le NetworkService.Vous pouvez faire une classe abstraite, puis d'écrire quelque chose comme ça:

public class ExchangeHandler extends AbstractHandler { 
    @Inject 
    ExchangeHandler(@Exchange NetworkService service) { 
     super(service); 
    } 
} 

Vous voulez avoir 2 instances distinctes qui utilisent le code exactement identique sauf pour obtenir l'instance NetworkService. Il y a plusieurs façons de le faire mais celle-ci semble être la plus lisible pour le moment. Sinon, vous pouvez envisager d'utiliser l'inversion de contrôle pour passer NetworkService dont vous avez besoin au moment au lieu de créer 2 arbres distincts d'objets pour Exchange et Reaml gestionnaires.

class ClassUsingManagers { 
    @Inject 
    ClassUsingManagers(
      @Exchange NetworkService exchangeService, 
      @Realm NetworkService realmService, 
      NetworkServiceHandler handler) { 
     handler.actionForService(exchangeService); 
     handler.actionForService(realmService); 
    } 
} 

ou si vous voulez juste pour les initier et exécuter une méthode (qui initialise tout le reste):

Multibinder serviceSet = Multibinder.newSetBinder(binder(), NetworkService.class); 
serviceSet.addBinding().asEagerSingleton(); 

une alors:

class ClassUsingManagers { 
    @Inject 
    ClassUsingManagers(
      Set<NetworkService> services, 
      NetworkServiceHandler handler) { 
     for(NetworkService service : services) 
      handler.actionForService(service); 
    } 
} 

Cette autre méthode serait vous obliger à installer l'addon de Guice Multbinding à Guice.

+0

il y a des conflits, je vais voir des annotations de liaison, thx –

+0

J'ai ajouté un exemple pour montrer comment vous pourriez atteindre votre objectif. –

+0

merci mais qui ne fixe mon problème:] parce que je dois @Inject NetworkService dans NetworkServiceHandler, et il doit être NetworkService sans annotation, parce que c'est une Wich « interface » est utilisé pour créer de nouveaux services .. exemple, je peut-être ajouter le sujet Shopmanager –

0

Je vous recommande d'utiliser une liaison de annotation pour distinguer les injections de NetworkService, peut-être:

@ManagesExchange NetworkService 
    @ManagesRealm NetworkService 
+0

ok, mais où? expliquer s'il vous plaît –

+0

sujet mis à jour, votre peut voir. –

+0

Dans votre reliure (voir le wiki: https://code.google.com/p/google-guice/wiki/BindingAnnotations) – Fred

Questions connexes