2

I've read that explicitly requesting an object instance from a DI mechanism is considered a general anti-pattern for DI/IoC. This is because, by the time the object comes into scope, it should have already been injected with all the dependencies it needs. In Guice-land, such an anti-pattern would be represented as:

Service svcImpl = (Service)injector.getInstance(Service.class);

Apparently, the one exception to this anti-pattern is the bootstrapping/dependency resolution phase, where you ask Guice for all the top-level root ("root" in the sense that all other objects flow from it) objects.

Interestingly enough, I can't find any practical, working code examples of this bootstrap process after an exhaustive online search! I would imagine it looks something like this:

public void bootstrap() {
    RootObj1 root1 = (RootObj1)injector.getInstance(RootObj1.class);
    RootObj2 root2 = (RootObj2)injector.getInstance(RootObj2.class);

    this.root1 = root1;
    this.root2 = root2;

    // Since all objects flow from these two "root" dependencies, bootstrapping
    // is complete. root1 and root2 contain all the dependencies the application
    // needs from here on out, and the "injector" object is no longer needed.
    // More importantly, injector is never used anywhere else in the code, and
    // therefore the code is not in violation of this anti-pattern.
}

Is this correct, or am I way off-base here? I ask only because I can't find any working examples!!

As I write this I'm beginning to second-guess myself because this just doesn't seem feasible/practical.

This is because, in reality an application's dependency graph will be massive with many separate, disparate "dependency trees", each with their own roots. This would lead to the necessity for some kind of Bootstrapper object, responsible for returning the roots of each of these trees so that all other objects across the codebase could request the appropriate root object to the "tree" they belong to. This is already sounding extremely convoluded.

A working code example of how bootstrapping is practiced in the real world might help bring some clarity to this for me. Thanks in advance!

4

1 回答 1

2

我认为你很难找到一个好的例子的原因是因为你让它变得比它需要的更复杂。引导并不比您的代码片段复杂,除了您可能需要调用一个方法root1root2让您的应用程序开始执行它所做的任何事情!

其余的只是由 Guice 处理。任何在执行过程中被实例化的对象都通过一个带注释的@Inject构造函数(或方法)从 Guice 获得它需要的东西。不需要有一个 Boostrapper 对象来控制所有树的所有根,因为 DI 容器管理所有实例。如果一棵树中的对象需要另一棵树中的对象,您就是@Inject它!无需为此“询问” Bootstrapper 对象。对于有背景的人来说,这有时很难想象ServiceLocator,但它确实是设计课程的一种更有凝聚力的方式。

Guice 有几个用于管理依赖图的工具。不同的依赖树是通过模块管理的,模块只是一组内聚的绑定。因此,Guice 鼓励您封装功能并让注入器解决相互依赖关系。此外,Guice 直到需要时才实例化图(除了可以急切加载的单例),开发人员可以使用Provider接口和方法显式延迟实例化。

如果您解释一下您希望将 Guice 用于哪种应用程序,或者解释一下您习惯使用哪种应用程序,也许会有所帮助。这将使我们更好地了解什么是没有意义的。

于 2012-04-15T03:43:05.430 回答