Guice 3 - 使用辅助注射时自动构建对象图

时间:2015-09-27 11:08:23

标签: java dependency-injection guice

我感兴趣的是构建具有依赖关系的对象的正确方式是什么,这些依赖关系本身具有@Assisted参数。一个例子将更好地说明:

普通的依赖关系没有@Assisted参数,你可以简单地拥有一个复杂的对象层次,这些对象都有它们的依赖关系并且这些注入没有问题,我只能得到一个对象的实例及其所有的依赖关系将生成并注入而无需我做任何事情。

但是如果我想改变它,那么对象层次结构中的一些依赖项有@Assisted参数,那么我必须自己使用工厂创建这些实例,即:

public SomeConcreteService(@Assisted String string) {
    this.string = string;
}

MyFactory myFactory = injector.getInstance(MyFactory .class);
SomeService myService = factory.getMyService("some string");

这会导致对象的干净实例化出现问题,因为我必须手动创建这些实例。并将它们传递给所需的对象,这实际上为该对象提供了多余的DI我认为????即然后我需要使用new关键字并手动传递所有依赖项...

new MyComplexObject(myService, myOtherService)

如果一个或多个依赖项使用@Assisted参数,我如何制作它以便我不必手动构建对象图?

1 个答案:

答案 0 :(得分:1)

您需要问自己的问题是,"为什么我要制作此@Assisted,以及谁将创建这些对象?"

如果你使用密钥来获得你需要的实例,那么你所拥有的就可以了:

public class YourInjectableClass {
  @Inject private MyFactory factory;

  public void doStuff(String key) {
    // You have a key, and your factory, so you can create the instance yourself.
    SomeService service = factory.getMyService(key);
    // [...]
  }
}

但是如果你使用密钥来获取一个实例创建一个实例来创建一个实例来获得你需要的东西,那么这似乎有问题。对于child injectors来说,这可能是一个更好的问题:

public class YourInjectableClass {
  @Inject private Injector injector;
  public void doStuff(String key) {
    // You need an OuterObject. So rather than calling
    // new OuterObject(new InnerObject(factory.getMyService(key))), do:
    OuterObject outerObject =
        injector.createChildInjector(new OuterObjectModule(key))
        .getInstance(OuterObject.class);
    // [...]
  }
}

因为整个依赖关系树都需要您的值,所以您可以将其视为注入依赖项。这可能会让您感到更加困惑,但是可以避免让您的依赖关系一直关注实例化细节。

或者,您可以创建手动调用new的手动OuterObjectFactory外观。这可能是遗留代码的更好解决方案,但可以通过确保一个类负责抽象实例化细节来帮助遵循单一责任原则。

N.B。我假设SomeConcreteService采用对象图可以提供的其他依赖关系。如果没有,那么根本没有理由使用注入:给SomeConcreteService一个公共构造函数并在需要时调用new SomeConcreteService("your value here")。尽管Guice花费了一些精力去抽象new的使用,但也没有必要创建数据对象或依赖项轻量级对象,如HashMapDate