Guice的目的

use*_*936 26 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);
}
Run Code Online (Sandbox Code Playgroud)

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

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

    barFooer.fooThatBar();
}
Run Code Online (Sandbox Code Playgroud)

现在我基本上得到了依赖注入的好处,对吧?更容易测试等等?当然,如果你想要,你可以轻松地更改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();
}
Run Code Online (Sandbox Code Playgroud)

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

所以我觉得我错过了一些非常基本的东西.你能否向我解释一下Guice方式如何有利?

提前致谢.

A.H*_*.H. 20

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

在进行"手动DI"时,这意味着您必须手动更改所有组件及其传递依赖关系的所有路径.这可能只是一些工作.

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

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

这更令人沮丧.

编辑为了澄清最后一点:图像你有一些深层嵌套的逻辑(10级或更多级别).在底部,你的逻辑应该根据某些值创建一个工厂,例如实际温度:如果"温暖"则需要a Cooler,如果"冷",则a Heater.两者都有接口TemperatureAdjustor.双方CoolerHeater需要得到他们的工作做了很多不同的依赖.

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

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