看起来您过度使用“依赖”的概念。您应该首先将封装用户输入(实际上是任何数据)的类与包含业务逻辑的类分开,然后您应该通过方法而不是通过注入传递这些数据,因为用户输入不是依赖项。
这样你几乎不需要辅助注入,因为你可以直接创建“数据”类new
(这没关系,因为它们没有依赖关系),并且“行为”类可以通过构造函数以标准方式相互注入。然后“行为”类将起作用,传递“数据”类的对象,而不是将它们作为依赖项。您将看到对辅助注入的需求消失了,您的程序变得更加简单易懂。
例如,而不是像下面这样:
public class OtherDependency {
private final int s;
@Inject
OtherDependency(@Assisted int s, ...) {
this.s = s;
...
}
public void doWork() { /* use s */ ... }
}
public class SumService {
private final int x1;
private final int x2;
private final OtherDependencyFactory depFactory;
@Inject
SumService(@Assisted int x1, @Assisted int x2, OtherDependencyFactory depFactory) {
this.x1 = x1;
this.x2 = x2;
this.depFactory = depFactory;
}
public void doWork() {
int s = x1 + x2;
OtherDependency dep = depFactory.create(s);
dep.doWork();
}
}
public class EntryPoint {
private final SumServiceFactory sumServiceFactory;
@Inject
EntryPoint(SumServiceFactory sumServiceFactory) {
this.sumServiceFactory = sumServiceFactory;
}
public void start() {
Scanner sc = new Scanner(System.in);
int x1 = sc.nextInt();
int x2 = sc.nextInt();
SumService sumService = sumServiceFactory.create(x1, x2);
sumService.doWork();
}
}
(显然,我对您的程序了解不多,但这是我在看到“首先需要用户输入的依赖链”时想到的)
你应该做类似的东西
public class OtherDependency {
@Inject
OtherDependency(...) {
...
}
public void doWork(int s) { /* use s */ ... }
}
public class SumService {
private final OtherDependency dep;
@Inject
SumService(OtherDependency dep) {
this.dep = dep;
}
public void doWork(int x1, int x2) {
int s = x1 + x2;
dep.doWork(s);
}
}
public class EntryPoint {
private final SumService sumService;
@Inject
EntryPoint(SumService sumService) {
this.sumService = sumService;
}
public void start() {
Scanner sc = new Scanner(System.in);
int x1 = sc.nextInt();
int x2 = sc.nextInt();
sumService.doWork(x1, x2);
}
}
所有用户输入都通过方法参数从一个类传递到另一个类,这些类本身是无状态的,只是正常注入。根本不需要使用辅助注射。
更新
我已阅读您的更新。有多种可能性可以做您想做的事,但复杂性各不相同。
首先,最简单的变体之一(我认为在这些情况下最好的变体)再次是通过方法调用传递您的输入数据。我看不出您的架构如何禁止这样做。只需让所有KnowledgeBaseService
需要此数据的方法都接受它,然后从InfrastructureService
. 您不需要在这里进行辅助注射。
其次,您可以在创建注入器之前获取用户输入,然后进行toInstance()
绑定。这取决于实际的架构,因此可能无法正常工作。我相信这是最简单的方法,它提供了非常简单和灵活的结构。
第三,您可以使用提供程序。为您创建一个提供者,ConfigDataObject
它要求用户输入并创建相应的实例,然后在范围内绑定ConfigDataObject
到它。Singleton
如果用户输入没有失败,这将起作用,因为您不应该从提供者那里抛出异常。如果您需要用户输入验证,请使用throwing providers扩展。用户输入将在第一次访问提供者时触发,然后由于其范围,结果将被缓存。
可能还有其他方法,但这些是我能够想出的。