Java 什么时候辅助注射有用?

Java 什么时候辅助注射有用?,java,guice,assisted-inject,Java,Guice,Assisted Inject,我目前正在我的应用程序中使用Guice。然而,我发现自己主要使用辅助注入,因为有一系列注入对象都依赖于程序的输入。 因此,几乎一切都是辅助注射 例如,A需要B,c需要Z,Z需要从命令行输入。最后我觉得一切都会得到帮助。因此,考虑到我一直在使用它,我想确保我使用它是正确的 我个人觉得写自己的工厂也一样好。此外,除了相同的优势外,我还可以进一步限制这些工厂创建相关对象 因此,我的问题是,使用辅助注射到底有多大用处,只是同时使用辅助注射和非辅助注射的想法吗?如果在我的例子中,你只有辅助参数呢 他们一定

我目前正在我的应用程序中使用Guice。然而,我发现自己主要使用辅助注入,因为有一系列注入对象都依赖于程序的输入。 因此,几乎一切都是辅助注射

例如,A需要B,c需要Z,Z需要从命令行输入。最后我觉得一切都会得到帮助。因此,考虑到我一直在使用它,我想确保我使用它是正确的

我个人觉得写自己的工厂也一样好。此外,除了相同的优势外,我还可以进一步限制这些工厂创建相关对象

因此,我的问题是,使用辅助注射到底有多大用处,只是同时使用辅助注射和非辅助注射的想法吗?如果在我的例子中,你只有辅助参数呢

他们一定是在用辅助注射来组织它方面有所收获。我就是看不出来

如果有人能在这里启发我,我将不胜感激

非常感谢

附言:

我的依赖性如下:

我有一个基础设施服务,它需要一个知识库服务,而知识库服务反过来又需要一个配置数据对象。我的configDataObject包含来自程序输入的信息。configDataObject在对这些输入进行验证和处理后存储这些信息。例如,可以向它提供一个表示文件路径的字符串,它将验证该文件是否存在,并使用getter方法将该文件返回给其使用者。其他事情可能是URLNname到真实的URL对象,等等

这里重要的一点是下图:InfrastructureService->KnowledgeBaseService->ConFigDataObject->InputData

因此,InfrastructureService只能与使用正确的输入文件、URL、工作文件夹等启动的knowledgeBaseService一起使用。。。。它与configDataObject一起提供给它,configDataObject从程序的输入接收它们并存储它们的处理版本

因此,到目前为止,我要做的是让一家辅助工厂创建知识库服务。它将ConfigDataObject作为参数。configDataObject是使用factoryMethod(Scala伴生对象)创建的。最后,还将为InfrastructureService创建一个辅助工厂,该工厂将KnowledgeBaseService作为其创建方法的参数


你可以猜到,所有的东西都是预先创建的,而且是手动创建的。我觉得很奇怪

看起来你过度使用了“依赖”的概念。您应该首先将封装用户输入(实际上是任何数据)的类与包含业务逻辑的类分开,然后您应该通过方法而不是通过注入来传递这些数据,因为用户输入不是依赖项

通过这种方式,您几乎不需要辅助注入,因为您可以使用
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()
bind。这取决于实际的体系结构,因此可能无法正常工作。我相信这是最简单的方法,提供了非常简单和灵活的结构

第三,您可以使用提供者。为您的
ConfigDataObject
创建一个提供者,该提供者请求用户输入并创建相应的实例,然后在
Singleton
范围中将
ConfigDataObject
绑定到它。如果用户输入没有失败,这将起作用,因为您不应该从提供程序抛出异常。如果需要用户输入验证,请使用扩展名。用户输入将在首次访问提供程序时触发,然后由于其范围,结果将被缓存


可能还有其他的方法,但这些都是我能想到的。

看起来你过度使用了“依赖”的概念。您应该首先将封装用户输入(实际上是任何数据)的类与包含业务逻辑的类分开,然后您应该通过方法而不是通过注入来传递这些数据,因为用户输入不是依赖项

通过这种方式,您几乎不需要辅助注入,因为您可以直接使用
new
(因为它们没有依赖关系)和“行为”创建“数据”类
object MyApp extends App {

  val config = ConfigData(args(0))

  val injector = Guice.createInjector(module(config))
  val service = injector.getInstance(classOf[InfrastructureService])

  println("The service name is:" + service.kbService.config.configName)

}


case class module(config: ConfigData) extends AbstractModule {
  def configure(): Unit = {
    bind(classOf[ConfigData]).toInstance(config)
  }
}

case class ConfigData(val configName: String)

class KbService @Inject() (val config: ConfigData)

class InfrastructureService @Inject() (val kbService: KbService)