谷歌guice:帮助注入

时间:2014-04-19 16:25:20

标签: java guice

我需要一些帮助来使用guice。 我的项目在这里:https://github.com/Romain-P/kalibro/blob/master/realm/src/org/kalibro/core/Main.java

我的问题:我需要在这个Main.java中替换3个注射器,只需要1个注射器。

我的申请是分开的: LoginServer和WorldServers。 你只需要1个realmServer和一些WorldServers。

现在,我刚刚创建了realmServer。你有: - RealmManager(管理玩家< - > loginServer) - ExchangeManager(管理世界< - > loginServer)

他们接受联系,他们用netty创建客户。 RealmManager& ExchangeManager扩展了NetworkService。

NetworkService是一个abstractClass,可以根据需要创建所有管理器。想象一下,如果我以后想要创建与webServer说话的shopManager。

请参阅代码:https://github.com/Romain-P/kalibro/tree/master/realm/src/org/kalibro/network/netty

现在,我的Main.java有3个注射器,但我需要只有1个。 这确实有效!但我认为它没有清理,所以我需要只有一个注射器。

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

模块:

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

2 个答案:

答案 0 :(得分:3)

Guice injector有...数组作为参数:

Guice.createInjector(Module... modules);

所以你可以这样做:

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

如果存在一些冲突,您可以尝试binding annotationsuntargetted bindings

编辑:

这可能会说明如何避免冲突:

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

然后:

@Inject
@Exchange
private NetworkService exchangeService;

编辑2:

我认为最大的问题是您启动NetworkService的方式。你可以把它变成一个抽象类,然后写出类似的东西:

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

除了获取NetworkService实例之外,您希望有2个不同的实例使用完全相同的代码。有几种方法可以做到这一点,但这个方法似乎是目前最具可读性的。或者,您可以考虑使用Inversion of Control来传递您目前所需的NetworkService,而不是为ExchangeReaml经理创建2个不同的对象树。

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

或者如果您只想启动它们并运行一个方法(初始化其他所有方法):

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

然后:

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

其他方法需要您将Guice Multbinding插件安装到Guice。

答案 1 :(得分:0)

我建议使用绑定annotation来区分NetworkService的注入,可能是:

  @ManagesExchange NetworkService
  @ManagesRealm NetworkService