【问题标题】:Dependency Injection with runtime data: Factories and direct dependencies运行时数据的依赖注入:工厂和直接依赖
【发布时间】:2017-07-12 08:31:55
【问题描述】:

我对依赖注入有一个一般的理解问题,独立于特定的依赖注入框架。假设我有一个需要运行时参数的类:

class ClassWithRuntimeDependency {
  ClassWithRuntimeDependency (String myRuntimeParameter) {
    //...
  }
}

现在要将这个运行时参数放入我的类中,几个依赖注入框架的文档告诉我使用工厂。这个工厂接受运行时参数并用它创建一个ClassWithRunetimeDependency 的实例。

但是假设ClassWithRuntimeDependency 是一个非常基本的类,几乎所有其他类都需要它: Class A -> Class B -> Class C -> Factory<ClassWithRuntimeDependency>.

现在我也无法创建没有这个运行时依赖的类 C,所以我需要为它创建一个工厂。但同样适用于 A 类和 B 类!这导致类 A 的工厂具有运行时依赖项,该依赖项仅在构造 ClassWithRuntimeDependency 时需要。这意味着我不会将直接依赖项注入到 A 类中,这也不是最佳实践 (github)。我知道我也可以将这种运行时依赖项引入所有需要的方法,而不是到处使用工厂,但这只会转移问题。

我这里有什么误解还是有更好的解决办法?


为了进一步表达这个问题,如果我在任何地方都使用工厂,这可能是我的 A-C 类:

// Needs a factory because of runtime parameter. 
// Imho, this is the only class which should really need a factory because 
// it is the only class having the  direct runtime dependency, all 
// others below are indirect
class ClassWithRuntimeDependency {
  ClassWithRuntimeDependency (String myRuntimeParameter) {
    //...
  }
}

// Needs a factory because of runtime parameter in ClassWithRuntimeDependendcy
class C {
  C(String myRuntimeParameter, @inject FactoryForClassWithRuntimeDependency reallyNeededFactory) {
    this.withRuntimeDependency = reallyNeededFactory(myRuntimeParameter);
  }
}

// Needs a factory because of runtime parameter in C -> ClassWithRuntimeDependendcy
class B {
  B(String myRuntimeParameter, @inject FactoryForC cFactory) {
    this.c = cFactory(myRuntimeParameter);
  }
}

// Needs a factory because of runtime parameter in B -> C -> ClassWithRuntimeDependendcy
class A {
  A(String myRuntimeParameter, @inject FactoryForB bFactory) {
    this.b = bFactory(myRuntimeParameter);
  }
}

(我没有使用特定DI框架的语法)

所以我最终得到了一个 AFactory,其依赖项只有 ClassWithRuntimeDependency 需要。当然,我也可以省略构造函数中的参数并仅使用它的方法(as suggested here),但如果我在这些类中的任何一个中有许多需要此参数的方法,这真的会炸毁我在所有依赖类中的 API ,因此只是转移了问题。

到目前为止我想出的唯一解决方案是注入一个context 对象(或context 对象的提供者),并用运行时数据填充这个上下文对象。但这也会导致temporal coupling 并使其更难测试。

【问题讨论】:

  • 您可以考虑将某种运行时上下文自动装配到您的应用程序中,而不是将您的参数推送到您的类中。所以每个类都可以自己获取运行时参数。
  • 你的基本假设是错误的。如here 所述,您的应用程序组件在初始化期间应该需要运行时数据。
  • @Toni,你没有详细介绍,但你看过 Guice 的AssistedInject吗?
  • @Toni,实际上这是这种方法的一个优势。您必须模拟该上下文,Spring 会自动将其注入到您的对象中以进行测试。只要您能够轻松地模拟它们,依赖关系对于测试来说并不坏。
  • 你认为这可能是this questionthis one 的欺骗吗?就我个人而言,我是前者的儿童注射器解决方案的粉丝,并且认为它会很好地适用于您的用例。

标签: java spring dependency-injection guice


【解决方案1】:

这就是为什么你应该有控制反转容器并让他为你做肮脏的工作。就像 Spring 一样。你只需通过配置指出你的 bean 需要什么样的依赖,然后 Spring 注入这个依赖。

【讨论】:

  • 你没有解释如何用 Spring 解决这个问题。您说明 OP 已经知道的内容(有一个 IoC 容器)。抱歉,这不是一个好的答案。 -1 直到改进发生。
猜你喜欢
  • 1970-01-01
  • 2012-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-20
相关资源
最近更新 更多