2

可能重复:
什么是控制反转?

我真的对依赖注入的概念感到困惑。

我对软件领域很陌生,我对以下情况有疑问。假设Json我的 java 代码需要一个解析器类,所以我在使用参数Json执行 java 程序时添加了 jar 。classpath我的程序依赖于Jsonjar,所以这意味着我在这里进行依赖注入

另一个例子是,usingimport语句确实解决了用户类依赖于其他类的问题(比如Date在 java 中)所以所有这些都是依赖注入的概念吗?

我在哪里提出这个概念。

提前致谢。

4

5 回答 5

8

这更多地与您如何将组件链接在一起。例如,在上面,我希望您将解析器注入需要它的类中。例如

代替:

public class MyParserUsingClass {
   ...
   public MyParserUsingClass() {
      this.parser = new Parser();
   }
}

你会这样做:

public class MyParserUsingClass {
   ...
   public MyParserUsingClass(Parser injectedParser) {
      this.parser = injectedParser;
   }
}

为什么要这样做?您使用解析器的类并不真正关心解析器的来源,并且应该真正使用接口而不是具体实例。通过注入解析器,您可以根据情况提供不同的实例,将其模拟出来进行测试等。否则该类只会在内部创建它,而您将无法控制它。这对于可配置组件、跨网络通信的组件、重量级组件等尤其重要。

于 2012-12-05T11:47:43.013 回答
1

在您的具体示例中,依赖注入看起来像:

public class MyParser {
     private final JsonParser parser;

     public MyParser(JsonParser parser) {
         this.parser = parser;
     }

     public Result parse(JsonInput input) {
         Result = parser.parse(input);
     }
}

假设这JsonParser是一个接口,您现在可以提供该接口的任何实现,MyParser而不依赖于您选择使用的特定实现。

于 2012-12-05T11:47:55.377 回答
1

假设您有一个名为 daes 的类MyCustomParser。现在您希望允许在该类中注入解析器以获得针对您将注入的解析器类型的不同行为(json 可能会更改,您想使用另一种解析方式等)。因此,您应该使用(通过实例)调用的方法创建一个Interface- 现在您可以根据您想要进行解析的方式对该方法进行不同的实现。您需要做的就是将此接口传递给将使用它的类(您可以将其作为构造函数中的参数传递)。在这种情况下,您将在类中注入 ParserIParserParseItMyCustomParserMyCustomParser

于 2012-12-05T11:52:42.087 回答
1

严格意义上的依赖注入与导入类或将 jar 文件添加到类路径无关。它旨在支持对接口原理的编程,它是一种控制反转的形式。

它带来的主要好处是你的代码不依赖于显式的依赖实现,而是使用抽象。您依赖于一个接口,并且该接口的实现类的某个实例将在运行时“注入”到您的类中(作为构造函数参数、某个 setter 或 - 在我看来是错误的选择 - 实例字段)。

因此,例如,您可以更改持久层而不接触服务组件中的代码,因为您的服务类只关心一些 DAO/Repository 接口,并且您将为它们提供不同的实现。

于 2012-12-05T11:53:32.083 回答
0

依赖注入更多的是关于减少一个类必须创建它自己依赖的事物的实例的实例。

依赖注入旨在通过某种外部机制将这些依赖“给予”给消费类。常用方法包括通过构造函数传入依赖项,或将它们设置为类的公开“可设置”属性。

例如,通过构造函数进行的依赖注入可能如下所示:

public class Parser
{
     private IJsonParser parser;

     public Parser(IJsonParser parser) {
         this.parser = parser;
     }
}

这消除了 Parser 类执行以下操作的需要:

public class Parser
{
     private IJsonParser parser;

     public Parser() {
         this.parser = new JsonParser();
     }
}

这遵循单一职责的原则——Parser 类不需要负责创建 JsonParser,也不应该关心它使用什么特定的 JsonParser——它的关注点只是它需要完成 IJsonParser 指定的工作的东西接口,并将其留给一些更高的控制代码来确定最适合完成这项工作的适当具体类型。

于 2012-12-05T11:46:27.920 回答