Java 什么是依赖注入?

Java 什么是依赖注入?,java,dependency-injection,import,jar,Java,Dependency Injection,Import,Jar,可能重复: 我真的对依赖注入的概念感到困惑 我对软件领域非常陌生,我对下面的场景有怀疑。假设我的java代码需要一个Json解析器类,所以我在使用classpath参数执行java程序时添加了Jsonjar。我的程序依赖于Jsonjar,所以这意味着我在这里进行依赖注入 另一个例子是,使用import语句确实解决了用户类依赖于其他类(如java中的Date)的问题,所以所有这些都是依赖注入的概念 我在这里提出这个概念 提前感谢。依赖注入更多的是减少实例,在这些实例中,类必须创建自己依赖的事物的

可能重复:

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

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

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

我在这里提出这个概念


提前感谢。

依赖注入更多的是减少实例,在这些实例中,类必须创建自己依赖的事物的实例

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

例如,通过构造函数的依赖项注入可以如下所示:

public class Parser
{
     private IJsonParser parser;

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

     public Parser() {
         this.parser = new JsonParser();
     }
}
这样就不需要解析器类执行以下操作:

public class Parser
{
     private IJsonParser parser;

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

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

这遵循了单一责任的原则-Parser类不需要负责创建JsonParser,也不应该关心它使用什么特定的JsonParser-它关心的只是它需要一些完成IJsonParser接口指定工作的东西,然后让更高级别的控制代码来决定最适合做这项工作的具体类型。

更重要的是如何将组件链接在一起。e、 在上面,我希望您将解析器注入到需要它的类中。e、 g

而不是:

public class MyParserUsingClass {
   ...
   public MyParserUsingClass() {
      this.parser = new Parser();
   }
}
你会做:

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

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

在您的特定示例中,依赖项注入看起来像:

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
,这不取决于您选择使用哪个具体实现。

假设您有一个类,该类的DAE作业名为
MyCustomParser
。 现在,您希望允许在该类中注入解析器,以获得与要注入的解析器类型不同的行为(json可能会改变,您希望使用另一种方式来解析等等)。 因此,您应该使用名为(按实例)
ParseIt
现在,根据您希望如何进行解析,您可以使用此方法的不同实现。 您只需将此接口传递给将使用它的类
MyCustomParser
(您可以将其作为构造函数中的参数传递)。
在本例中,您正在
MyCustomParser
类中注入解析器,严格意义上讲,依赖注入与导入类或向类路径添加jar文件无关。这是为了支持编程到接口的原则,这是一种控制反转的形式

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


因此,例如,您可以在不涉及服务组件中的代码的情况下更改持久性层,因为您的服务类只关心一些DAO/存储库接口,您将为它们提供不同的实现。

这根本不是依赖注入。谷歌IoC(控制反转)来获得更好的感觉。不,这两个都不是依赖注入;这些只是依赖关系。查阅“控制反转”来阅读这个主题。@assylias:我不这么认为。我把DI概念和其他概念混淆了。我没有问它到底是什么。
为什么这样做?
解释+1。谢谢