面试官:依赖注入是啥?你懂吗
IOC DI 这到底是个啥
hi 各位小伙伴,今天跟大家聊聊控制反转和依赖注入到底是个啥?
在了解过程中看了很多的资料 如果有不正确的希望大家跟我联系,一起学习
本次文章分为以下三个部分
- IOC 和DI 是什么
- IOC 和DI带来的好处
- java中如何使用IOC和DI
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 第三版