什么是依赖注入?

IOC 和 DI 是什么

控制反转(Inversion of Control,缩写为 IoC),是 面向对象编程 中的一种设计原则,可以用来减低计算机代码之间的 耦合度 。其中最常见的方式叫做依赖注入(Dependency Injection,简称 DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体,将其所依赖的对象的引用传递(注入)给它。

控制反转到底反转的是什么,控制的又是什么,依赖注入 注入的是什么,依赖的又是什么?

首先让我们忘记控制反转来看依赖注入,因为 04 年的时候马丁大叔就控制反转这个词语提出一种更加易懂的解释叫依赖注入,了解依赖注入才能更好理解控制反转。下面通过一个例子来引出依赖注入。

每个文本输入框有一个文本检查器,每次初始化一个文本选择框都需要一个检查器。

public class TextInput {
    private  SpellCheck spellCheck;
    public TextInput() {
        spellCheck=new SpellCheck();
    }
}
public class TextInput {
    private  SpellCheck spellCheck;
    public TextInput(SpellCheck spellCheck) {
        this.spellCheck=spellCheck;
    }
}

观察以上两段不同的代码我们可以发现他们本质的区别是 SpellCheck 对象创建的时间以及地点不同,在后面代码中文本检查器作为一个文本框的构造方法中的一个形参传入文本框内部。即可以了解为将 spellCheck 对象注入 TextInput 类。通过这个例子大概就可以了解上面提出的问题,什么是依赖,什么是注入了吧,文本框依赖 检查器 ,将依赖的类作为 形参放入依赖的类中 就成为依赖注入。

接下来就是控制反转了,写过 java web 的同学一定使用过一个注解@Autowired,通过这个注解就可以直接生成一个类对象,而不需要显式 new 一个出来。当我们可以控制一个对象何时生成时这便是控制,而通过 IOC 容器将对象的创建权夺走,这便是权力反转(可以理解为调用代码的变更频率切换到被调用代码那里)。

理解了上面的概念,其实你就知道控制反转是依赖注入的 web 应用,专门使用一个容器对要注入的类进行管理。方方便了用户在类外重复创建依赖类。所以深入了解依赖注入是重点,而控制反转是 DI 的应用。如 Martin 说的“哪些方面的控制被反转了?”这个问题。他总结出是依赖对象的获得被反转了,

下面让我们来聊聊依赖注入到底有什么好处,以及依赖注入的几种方法。

在让我们通过代码来了解他的好处

public class Car {
    private enginer enginer;
    private wheel wheel;

    public Car() {
        enginer = new enginer();
        wheel = new wheel();
    }
}
public class Car {
    private enginer enginer;
    private wheel wheel;

    public Car(enginer enginer, wheel wheel) {
        this.enginer = enginer;
        this.wheel = wheel;
    }

汽车是一个复杂对象,其中包括许多的组件,发动机,轮子等等, 各种各样的汽车总是大同小异,轮子的尺寸,当我们想要创建两辆不同的车的时候,但他们只有轮子的大小不同时 方案 1 要创建一个新 car 类在构造函数中新 new 一个 wheel 对象,而方案二,只需要在外面创建 wheel 对象传入 car 类就可以。减少了新建 Car 类 。也就是说减少了类之间的耦合,对象在运行时而不是在编译时(汽车制造时)被赋予它们的依赖关系。 所以我们现在可以随时改变车轮。 在这里,依赖(车轮)可以注入到汽车在运行时间。同时这是一种非常有用的测试技术,因为它允许对依赖关系进行模拟或删除。

通过上面大家应该了解依赖注入了除了通过构造函数还有哪几种方式来实现依赖注入呢?

依赖注入有如下实现方式:

  • 基于接口。实现特定接口以供外部容器注入所依赖类型的对象。
  • 基于 set 方法。实现特定属性的 public set 方法,来让外部容器调用传入所依赖类型的对象。
  • 基于构造函数。实现特定参数的构造函数,在新建对象时传入所依赖类型的对象。
  • 基于注解。基于 Java的注解功能 ,在私有变量前加“@Autowired”等注解,不需要显式的定义以上三种代码,便可以让外部容器传入对应的对象。该方案相当于定义了 public 的 set 方法,但是因为没有真正的 set 方法,从而不会为了实现依赖注入导致暴露了不该暴露的接口(因为 set 方法只想让容器访问来注入而并不希望其他依赖此类的对象访问)。

ok。ioc 和 di 就介绍到这。如果上面有错误 请大家及时联系我并提出,不胜感谢。

参考文献 Effective java 第三版 wikiwhat is dependency injectionWhat is Inversion of Control?DI 提出者原文 spring ioc di 理解

参考:

https://juejin.cn/post/6844904071657160717

https://www.cnblogs.com/maigy/p/10808308.html

你可能感兴趣的:(软件研发,java,spring,设计模式,python,面试)