Guice:为共享库创建注入器

时间:2012-01-13 14:45:53

标签: java dependency-injection guice

Google Guice新手。我想用它来处理我正在开发的三个组件的所有IoC和AOP方法拦截:

  • WidgetClient - 一个Swing应用
  • WidgetServer - 客户端将连接到/与
  • 通信的小型EAR
  • WidgetShared - 包含客户端和服务器使用的公共类的“commons”JAR

使用Swing应用程序,我会在某个地方进行显式调用:

public static void main(String[] args) {
    initGuiceInjectors();
}

private static initGuiceInjectors() {
    Guice.createInjector(mySwingAppModule);
}

mySwingAppModule将定义Swing应用程序依赖项的所有绑定。我将在服务器EAR中做一些非常相似的事情。

说到WidgetShared库,我很窒息,因为lib没有一个入口点:它只是一堆包,类,接口和枚举,客户端和服务器将在整个地方使用。

所以我的第一个问题是:我在哪里为Guice.createInjector() JAR调用WidgetShared

这个问题强调了第二个(类似的)问题,这就是为什么我选择在这里进行分组。

我阅读了Guice的“最佳实践”,并且压倒性的共识似乎是(在适用的情况下),在包级别保持Module实现。因此,对于每个包,将有一个Module具体定义该包中所有类型的绑定。这是对整个应用程序的单个Module定义绑定的改进。

因此,上面的代码段(Guice.createInjector(mySwingAppModule))实际上是我的代码最终会是什么样的(抱歉我撒了!)。

我的第二个问题是:创建多个注射器的“最佳实践”是什么?

我看到createInjector(Module... modules)可以采用vararg Module参数。所以,对我来说,似乎我想拥抱这个“ 1-module-per-package ”最佳实践,在某些时候我必须拥有如下所示的代码:

Guice.creatorInjector(package1Module, package2Module, package3Module,
    package4Module, package5Module, package6Module, ..., packageNModule);

或者,像这样:

Guice.createInjector(package1Module);
Guice.createInjector(package2Module);
Guice.createInjector(package3Module);

...

Guice.createInjector(packageNModule);

这两个看起来都很讨厌!有没有更好的方法来实现这个目标?!

提前致谢!

1 个答案:

答案 0 :(得分:4)

亚当,

你的问题有两个要素,但显然都是相关的。我会倒退,先从第二个元素开始。

每个程序包组织一个模块很重要,因为它提供了一个可预测的约束应该放置的约定,作为奖励,它允许您相应地打包保护您的类。还有一种流行的概念,即创建复合模块,主要用于安装每个包模块的集合,以便充当需要安装的单个模块,以便为库的给定配置添加绑定。安装此单个模块成为库与使用它的服务器/应用程序之间的主要集成点。

回到第一点,不建议每个应用程序有多个注射器。更好的方法是让一个注入器安装它所需的模块,以满足应用程序中使用的所有绑定。

最后,你会有类似的东西:

public WidgetSharedLibraryModule extends AbstractModule {
  @Override protected void configure() {
    install(new WidgetSublibraryModule1());
    install(new WidgetSublibraryModule2());
    ...
  }
}

您的主要方法如下:

public static void main(String[] args) {
    Injector injector = Guice.createInjector(
        new WidgetSharedLibrary(),
        new WidgetSwingAppModule());
    WidgetSwingApp app = injector.getInstance(WidgetSwingApp.class);
    app.run();
}