这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战
是什么
提到后端框架,经常听到的名词就是依赖注入和控制反转,这两个被java发扬光大的概念已经成了后端框架的一个最佳实践。那么问题来了,什么是依赖注入和控制反转?
依赖注入和控制反转是对同一概念不同角度的描述。
依赖注入(dependency injection),是指组件间的依赖关系由容器在运行期决定。这里的容器通常可以认为是运行框架,如Spring,Midway等。即组件之间的依赖关系是在运行的时候由容器进行注入的。
控制反转(inversion of control),是指组件依赖的内容不在对象内部进行控制引入,而是交给容器去进行控制(即反转)。
可见依赖注入强调的是容器的主体概念;而控制反转强调的是依赖控制权的转移(从组件内部转移到容器)。
为什么
依赖注入和控制反转,是一种思想,它降低了组件与组件之间的高耦合,使整个程序体系更为灵活。让我们不需要关心资源来自何处,由谁实现,只需要通过简单的配置,就能指定目标需要的资源,提高系统的灵活性及可扩展性。
实现
下面实现了一个简单的依赖注入的容器。简单介绍下实现的原理。
- 初始化容器的时候,执行init方法,检索文件,把类和类的内容存到一张映射表里
- 运行的时候,使用到某个类,调用get方法,先从缓存里查找,有直接返回
- 缓存没有,将这个类加入到缓存中,并对它的依赖进行递归处理
const globby = require('globby');
const path = require('path');
class Container {
cwd = process.cwd();
cache = {};
classTable = {};
init() {
const fileResults = globby.sync(['**/**.ts', '**/**.js'], {
cwd: this.cwd,
ignore: [
'**/node_modules/**',
],
});
for (const name of fileResults) {
const exports = require(this.cwd + '/' + name);
this.classTable[this.getName(exports)] = exports;
}
}
getName(Module) {
return Module.name.toLowerCase();
}
get(Module) {
if(this.cache[this.getName(Module)]) {
return this.cache[this.getName(Module)];
}
const obj = new Module();
this.cache[this.getName(Module)] = obj;
const properties = Object.getOwnPropertyNames(obj);
for(let p of properties) {
if(!obj[p]) {
if(this.classTable[p]) {
obj[p] = this.get(this.classTable[p]);
}
}
}
}
}
const container = new Container();
const a = container.get(A);