Guice的目的

时间:2012-10-19 16:35:18

标签: java dependency-injection guice

我(我想)理解依赖注入的目的,但我只是不明白为什么我需要Guice这样做(好吧,显然我不需要需要 Guice,但是我的意思是为什么使用它是有益的)。假设我已经存在(非Guice)代码,就像这样:

public SomeBarFooerImplementation(Foo foo, Bar bar) {
    this.foo = foo;
    this.bar = bar;
}

public void fooThatBar() {
    foo.fooify(bar);
}

在某个更高级别,也许在我的主要()中,我有:

public static void main(String[] args) {
    Foo foo = new SomeFooImplementation();
    Bar bar = new SomeBarImplementation();
    BarFooer barFooer = new SomeBarFooerImplementation(foo, bar);

    barFooer.fooThatBar();
}

现在我基本上得到了依赖注入的好处,对吧?更容易测试等等?当然,如果你想要,你可以轻松地更改main()以从配置而不是硬编码中获取实现类名。

据我所知,要在Guice中做同样的事情,我会做类似的事情:

public SomeModule extends AbstractModule {
    @Override
    protected void configure() {
        bind(Foo.class).to(SomeFooImplementation.class);
        bind(Bar.class).to(SomeBarImplementation.class);
        bind(BarFooer.class).to(SomeBarFooerImplementation.class);
    }
}

@Inject
public SomeBarFooerImplementation(Foo foo, Bar, bar) {
    this.foo = foo;
    this.bar = bar;
}

public static void main(String[] args) {
    Injector injector = Guice.createInjector(new SomeModule());
    Foo foo = injector.getInstance(Foo.class);

    barFooer.fooThatBar();
}
是吗?在我看来,这只是语法糖,而不是特别有用的语法糖。如果将“新的XxxImplementation()”内容分解为一个单独的模块而不是直接在main()中进行操作有一些优势,那么无论如何都可以轻松完成。

所以我觉得我错过了一些非常基本的东西。你能否告诉我Guice方式如何有利?

提前致谢。

2 个答案:

答案 0 :(得分:20)

在现实生活和更大的应用程序中,组件的级别不仅仅是2(如您的示例所示)。它可能是10或更多。需求和依赖性也可以随心所欲地改变。

当手工执行“DI”时,这意味着您必须手动更改所有组件及其传递依赖项的所有路径。这可能只是一些工作。

使用“真正的DI”(即Guice,Spring,CDI),您只需更改一个或两个受影响的组件和接线(Guice上的Module)就可以了。

另外:想象一下,您的一些深层嵌套组件位于工厂中,应由其他组件调用。在Guice中你只需注入一个Provider<Foo>就可以了。手动完成时,必须在整个代码中拖动工厂及其实例的依赖关系。

这更令人沮丧。

编辑澄清最后一点:图片你有一些深层嵌套的逻辑(10级或更多级别)。在底部,您的逻辑应基于某些值创建工厂,例如实际温度:如果“暖”,则需要Cooler,如果是“冷”,则为Heater。两者都有接口TemperatureAdjustorCoolerHeater都需要很多不同的依赖关系才能完成工作。

由于因子的实例类型无法在main中创建,因此请将其移至需要的位置。因此,您最终将两个工厂的依赖关系下移到需要它们的位置。 (“很多依赖”加上“很多依赖”是“太多不能保持理智”)

使用像Guice这样的“真正的DI”,你可以使用AssistedInject来避免依赖的混乱,只给出工厂的实际业务价值(这里是:温度)并完成。工厂的接线在模块中完成。

答案 1 :(得分:2)

手写的DI是真正的DI。

当您考虑IOC容器的复杂性时,您必须更深入地了解为什么要使用它。我很长一段时间都是反IOC,能够设计和实现干净,快速,整洁的手工编码,真正的DI。但我对容器的想法感到满意,因为它们有助于标准化实现,并提供更基于配置的机制,用于向依赖方程式添加新的决策。其他人已经为你写了这些内容,所以你不必花时间手工编码。

许多人说要在大型应用程序中使用容器,在小型应用程序中使用手动代码。我说的恰恰相反。小应用程序的性能不受限制。了解使用打包容器的实现速度。在大型应用程序中,您将花费大量时间进行优化,请考虑对DI进行手动编码。

编辑:但是我要补充一点,IOC容器或手工编码,总是使用DI和代码到界面 - 无论你正在使用多么简单的应用程序。即使在小应用程序中也可以编写出色的代码。