2015-09-27 40 views
1

我感兴趣什么是正确的方式来构建具有@Assisted参数的依赖关系的对象。一个例子更好地说明:Guice 3 - 使用辅助注入时自动构建对象图

Ordinarilly有没有@Assisted PARAMS的依赖,你可以简单地拥有对象,所有他们之间的依赖与这些获得注入没问题的复杂层次结构,我就可以得到一个对象的实例和它的所有依赖关系都将被生成并注入,而无需执行任何操作。

但是,如果我想改变它,有些依赖的对象层次有@Assisted PARAMS然后我要创建自己使用一个工厂,即那些实例:

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

你需要问自己的问题是,“为什么我要制作这个@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); 
    // [...] 
    } 
} 

因为你的价值需要在整个依赖关系树,你可以把它当作一个注入依赖。这可能会让你更加困惑,但是可以让你避免让依赖关注实例化细节。

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


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

+0

我其实没有真实世界的场景,我只是在想这件事。但是,即使“SomeConcreteService”不需要其他依赖关系,如果可以将其与Guice进行管理,可能仍然很好,例如,可以切换到另一个服务;只是想。 – Neilos

+0

关于你的回答,我认为大部分时间你的第一个例子就足够了。主要的变化是:注入工厂,并有一些基本的'init()'方法来初始化依赖项(我假设它将在整个类中多次使用),或者如果只是使用了一次,那么'doStuff )'方法就足够了。所以我需要添加额外的逻辑来传递密钥,就像你说的那样可以理解。你的第二个例子,但我不认为我完全理解,但我会花一些时间寻找它:) – Neilos