Guice 3 - 使用辅助注入时自动构建对象图
Guice 3 - Automatically building object graph when using assisted inject
我感兴趣的是构造具有依赖项的对象的正确方式是什么,这些依赖项本身具有 @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
参数,我该怎么做才能不必手动构建对象图?
你需要问自己的问题是,"why am I making this @Assisted
, and who is going to create these objects?"
如果您使用密钥获取您需要的实例,那么您拥有的就可以了:
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);
// [...]
}
}
但是如果你使用key来获取一个实例create an instance来创建一个实例来获取你所需要的东西,那么这似乎是有问题的。对于 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 facade。对于遗留代码,这可能是更好的解决方案,但可以通过确保一个 class 负责抽象实例化细节来帮助遵循单一职责原则。
N.B。我假设 SomeConcreteService
采用对象图可以提供的其他依赖项。如果不是,那么根本没有理由使用注入:给 SomeConcreteService 一个 public 构造函数并在需要的地方调用 new SomeConcreteService("your value here")
。尽管 Guice 费了一番功夫来抽象掉 new
的使用,但也没有必要创建数据对象或像 HashMap
或 Date
.
这样的轻依赖对象
我感兴趣的是构造具有依赖项的对象的正确方式是什么,这些依赖项本身具有 @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
参数,我该怎么做才能不必手动构建对象图?
你需要问自己的问题是,"why am I making this @Assisted
, and who is going to create these objects?"
如果您使用密钥获取您需要的实例,那么您拥有的就可以了:
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);
// [...]
}
}
但是如果你使用key来获取一个实例create an instance来创建一个实例来获取你所需要的东西,那么这似乎是有问题的。对于 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 facade。对于遗留代码,这可能是更好的解决方案,但可以通过确保一个 class 负责抽象实例化细节来帮助遵循单一职责原则。
N.B。我假设 SomeConcreteService
采用对象图可以提供的其他依赖项。如果不是,那么根本没有理由使用注入:给 SomeConcreteService 一个 public 构造函数并在需要的地方调用 new SomeConcreteService("your value here")
。尽管 Guice 费了一番功夫来抽象掉 new
的使用,但也没有必要创建数据对象或像 HashMap
或 Date
.