Guice injector.getInstance() - 良好的做​​法?

时间:2013-10-11 06:33:01

标签: java dependency-injection guice

假设我有两个应用程序共享同一个库。该库包含常见的类,如DAO,Utils等。共享库中的所有内容都与Guice连接。我的两个应用依赖于这个库,但没有直接依赖Guice。

 ______    ______    ______
|      |  |      |  |      |
| APP1 |->| LIB  |<-| APP2 |
'------'  '------'  '------'

我目前使用的是这样的东西:

static <T> Utils.getInstanceOf (Class<T> type);

这只是一个包装:

injector.getInstance (Class<T> type);

但是guice文档说:

  

如果可行,请避免使用此方法,而不是使用Guice   提前注入您的依赖项。

那么为两个应用程序提供依赖注入的最佳方法是什么,而无需在Guice模块中手动绑定它们?

5 个答案:

答案 0 :(得分:10)

  

那么为两者提供依赖注入的最佳方法是什么   应用程序,而无需在Guice模块中手动绑定它们?

没有这样的方法。你要么完全拥抱Guice,要么不使用它并明确地传递你的依赖。好吧,以这种方式构造你的代码,所以你永远不会直接创建类依赖,通过构造函数传递它们,也可能被称为'依赖注入',但我敢肯定这不是你的意思。如果你不想在你的应用程序中使用Guice,那么你将无法获得比getInstance()更好的东西,这很难看,特别是因为你正在使用 static 包装器。 / p>

理想情况下,您的库应该提供一个模块,您可以在应用程序中通过Guice.createInjector()安装,或者相反,库应该提供一个Injector实例,您可以在应用程序中使用它通过使用createChildInjector()并提供特定于应用程序的模块。对此方法的轻微修改是将特定于应用程序的模块传递给库,以便它们用于创建Injector。我最近在自定义类似servlet的界面上编写了基于Guice的API,使用最后一种方法完全不支持任何类型的DI,并且它运行良好。

在servlet或Jersey环境中使用Guice并不困难。例如,后者与Guice(至少在1.x版本中)具有开箱即用的集成。 Guice servlet extension也非常好,方便。试试吧,亲眼看看。

答案 1 :(得分:3)

  

static <T> Utils.getInstanceOf (Class<T> type);

您最终得到的是Service Locator

虽然在一些小案例中,injector可以接受其他创作对象,但我不认为这是其中之一。您最终得到了服务定位器的所有缺点,并且可以使用您已经使用的工具获得所有优势。

答案 2 :(得分:2)

使用注入器的“通常”模式是在项目的某个顶级入口点设置它(在servlet场景中,使用Guice-Servlet,这将是GuiceServletContextListener)。为了模块化,您可能希望在某个依赖项的入口点配置单个注入器,并使其负责连接该依赖项。如果在依赖项中同时需要单个绑定和父项目的绑定,则可以创建在未找到绑定的情况下委托给其父项的子注入器。 Guice支持这一点。

然而,我觉得你想在依赖项中设置一个注入器并在主应用程序中使用它似乎很奇怪。这意味着依赖关系知道主应用程序所需的所有绑定。我不太确定你用这种方法想要实现什么。是你的两个应用程序具有相同/非常相似的绑定设置,你不想重复它?在这种情况下,您应该定义一个具有所有绑定配置的模块(可能在依赖项中),并在每个应用程序的入口点设置注入器时使用它。那么多关于你的情况。

总的来说你的问题。我认为避免明确传递注入器是一种很好的做法。无论何时执行此操作,您都会将依赖注入的概念视为一个透明项目,并将自己绑定到具体的注入框架。在大多数情况下,您可以使用ProvidersFactories来避免对进样器的显式引用。

答案 3 :(得分:2)

如果您的方法需要在运行时创建类C的新实例,请将Provider绑定到您的类。 C将以通常的方式绑定,例如

public CModule extends AbstractModule {
    @Overide
    public void configure() {
        bind(C.class).to(CImpl.class);
    }
}

创建C实例的类将如下所示:

class UserOfC {
    private Provider<C> cProvider;
    ...

    @Inject
    UserOfC(Provider<C> cProvider, ...) {
        this.cProvider = cProvider;
        ...
    }

    public void doSomethingWithAC (...) {
        C myC = cProvider.get();  // not a singleton; new instance created!
        ...
    }
}

Guice支持提供者免费注射。如果绑定了C,则可以像注入C实例一样轻松地注入Provider。

其他建议:

我强烈建议您尽可能地在构造中注入所有依赖项,即使它需要编写更多代码行。我已经使用Guice多年了,还需要部分构造或任何其他高级功能。

当我面临部分注射的需要时,我通常会写自己的工厂。我发现在编写代码时更容易理解和调试。

答案 4 :(得分:0)

是的,可以通过这种方式传递注射器。

即使我们已经使用我们的wicket应用程序做了类似的事情,因此对于非非wicket页面,我们只使用injector.get.inject(this)并传入构造函数。

它完美无缺。

希望这有帮助。