当前位置: 首页 > 知识库问答 >
问题:

辅助注射什么时候有用?

韩单弓
2023-03-14

我目前正在我的应用程序中使用Guice。然而,我发现自己大多使用辅助注入,因为有一个注入对象链,它们都依赖于程序的输入。因此几乎所有的东西都是辅助注射的。

例如,A需要B,B需要c,c需要Z,Z需要来自命令行的输入。最后我感觉一切都将被辅助注射。因此,鉴于我坚持使用它,我想确定我使用它是正确的。

我个人觉得写我自己的工厂也一样好。此外,除了同样的优点之外,我还可以进一步将我所讨论的对象的创建限制在这些工厂。

因此,我的问题是,使用辅助注射到底有多有用,这只是同时进行辅助和非辅助的想法吗?如果像我的情况一样,你只有辅助参数呢?

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

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

非常感谢

PS:

我的依赖是这样的:

我有一个InfrastructureService,它需要一个KnowledgeBaseService,反过来又需要一个ConFigDataObject。我的configDataObject包含来自程序输入的信息。configDataObject在对这些输入进行一些验证和处理后存储这些信息。例如,可以向它提供一个表示文件路径的字符串,它将验证它是存在的文件,并使用getter方法将该文件返回给它的使用者。其他内容可能是URLName到真实的URL对象,等等。

这里重要的一点是下图:基础设施服务-

因此,基础设施服务只能与以正确的输入文件,URL,工作文件夹等启动的知识库服务一起使用。它与 configDataObject 一起提供给它,该对象从程序的输入中接收它们并存储它们的处理版本。

因此,到目前为止,我所做的是让一个assistedFactory创建知识库服务。它将ConfigDataObject作为参数。configDataObject是使用factoryMethod(Scala Companion Object)创建的。最后,还为InfrastructureService创建了一个assistedFactory,它将KnowledgeBaseService作为其创建方法的参数。

正如你所猜测的,一切都是预先创建的,而且是手动创建的。我觉得很奇怪。

共有2个答案

岑俊弼
2023-03-14

这是我所做的,最终以一种更优雅的方式解决了这个问题,而不是由于应用程序的参数而使用不必要的辅助注入链。

也就是说,如果像我的情况一样,您的数据来自命令行,那么我认为正确的方法是将输入数据结构的类型绑定到从命令行获得的实例输入结构:

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)

我相信这里的关键是提醒自己,模块可以用任何认为必要的输入数据进行参数化

赵立果
2023-03-14

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

这样,您几乎永远不需要辅助注入,因为您可以使用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);
    }
}

所有用户输入都通过方法参数从类传递到类,这些类本身是无状态的,只是正常注入。完全不需要使用辅助注射。

更新

我看了你的更新。做你想做的事情有多种可能性,复杂程度各不相同。

首先,最简单的一种方法(我认为是这种情况下最好的方法)是通过方法调用传递输入数据。我不明白你的建筑怎么会禁止这样做。只需让< code > knowledge base service 上需要此数据的所有方法接受它,并从< code > infra structureservice 传递它。这里不需要辅助注射。

其次,您可以在创建注入器之前获取用户输入,然后执行 toInstance() 绑定。这取决于实际的体系结构,因此可能无法正常工作。我相信这是最简单的方法,它提供了非常简单和灵活的结构。

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

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

 类似资料:
  • 我是Guice的新手,所以我试图理解AssistedInject。我有一个非常简单的项目: 我要注入的类: 带辅助注射的类别: 工厂 主类: 但它仍然不起作用,我不明白,我错在哪里?

  • 我正在使用Guice Assisted Inject库为我建立一个工厂。我目前的设置如下: 这迫使我使用< code > factory . create controller(first,factory . create second(first))显式创建一个< code>SecondDep。是否可以更改我的绑定,这样我就可以简单地执行< code > factory . create con

  • 我已经使用google-guice和辅助注射机制有一段时间了。因为我在scala,刚刚发现scala-guice,我也对使用它感兴趣。但是我对如何使用辅助注射感到困惑。没有使用辅助注射的例子。 因此,我的问题是:是否可以使用scala guice辅助注射,如果可以,请提供一个简单的例子? 此外,对于google-guice,我使用以下库:javax.inject.jar、guice-3.0.jar

  • 问题内容: 来自dagger-discuss @: 我有一个类,它从对象图中获取一些依赖关系,而在运行时从调用者那里获取其他依赖关系。 我想出了一个解决方案,定义了一个工厂, 现在,我不再注入客户端的构造函数,而是直接注入并调用其方法。 如您所见,这很冗长且冗长。它还有很多重复和样板。使用来注释字段本身存在一些障碍,因此让我们暂时忽略这种可能性。 Square人员使用提供程序提出了一个有趣的解决方

  • 我在实施辅助注射时遇到了错误。 辅助注射一直有效,直到我引入了另一个名为管理器的类,它依赖于辅助类。经理想要使用代码在构建喷油器图时中断。它没有更进一步。 直觉上,我理解当对象A得到帮助时,那么B(依赖于A)实际上也通过A得到了隐含的帮助。 请注意,我检查过了。我想像ColinD这样的人肯定知道答案如何使用Guice的AssistedInject?如何将辅助注入类绑定到接口? 出于好奇,有没有好的

  • 问题内容: 我知道这些问题听起来很愚蠢,但是在Java中,什么是辅助类,有人怎么写一个,以及编译器如何知道某种东西是辅助类? 编辑:我问这是因为编译器正在生成有关外部库中对象的警告,我想知道原因。 编辑2: 这是针对那些想要的人的编译器警告: 问题答案: 正如Java规范descried 在这里,你可以在一个java文件指定多个类。名称与.java文件名匹配的类将成为主要类,可以将其声明为公共类,