依赖注入的好处

要理解依赖注入(Dependency Injection), 控制反转(Inversion of Control), 控制反转容器(IoC Container), 首先要知道依赖倒置原则(Dependency Inversion Principle)

依赖倒置原则: 把原本的高层建筑依赖底层建筑”倒置”过来,变成底层建筑依赖高层建筑. 原来是 Controller -> Service, 改成 Controller <- Service. 顶层方法要什么, 底层方法去实现, 顶层方法不管底层是怎么实现的, 最后拿来给我用就行, 避免牵一发而动全身.

非依赖注入的原始代码

1
2
3
4
5
6
7
8
9
10
11
class Controller {
constructor() {
this.service = new Service();
}
}

class Service {
constructor() {}
}

const c = new Controller();

需求: 如果要改变 Service, 那么同时要改 Controller

1
2
3
4
5
6
7
8
9
10
11
12
13
class Service {
constructor(size: number) {
this.size = size;
}
}

class Controller {
constructor(size: number) {
this.service = new Service(size);
}
}

const c = new Controller(size);

基于依赖注入的代码

1
2
3
4
5
6
7
8
9
10
11
12
class Controller {
constructor(service: Service) {
this.service = service;
}
}

class Service {
constructor() {}
}

const s = new Service();
const c = new Controller(s);

同样的改变需求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Controller {
constructor(service: Service) {
this.service = service;
}
}

class Service {
constructor(size) {
this.size = size;
}
}

const s = new Service(size);
const c = new Controller(s);

可以看到, 只有与 Service 相关的部分作出了修改.

下面说说什么是依赖注入 & 控制反转

就像上面一样, Controller 是需要依赖 Service 的.
正常是把 Service 的创建放在 Controller 中, 依赖注入 就是把依赖的部分当做参数传入进去.

原来是 Controller 控制 Service 的创建和生命周期, 控制反转 就是 Service 控制了 Controller 的创建和生命周期.
Ps: 说是控制, 实际上 Controller 的创建需要依赖于 Service 的存在; Service 生命周期结束, Controller 即使在内存还在, 也无法使用, 名存实亡.

控制反转容器

非依赖注入的写法

1
const c = new Controller(size);

依赖注入的写法

1
2
const s = new Service(size);
const c = new Controller(s);

将依赖注入创建 Controller 的所有过程, 打包成一个整体, 基于配置文件或者外部参数控制的容器化方法, 即为控制反转容器

1
2
3
4
const ctlrFactory = (size) => {
const s = new Service(size);
const c = new Controller(s);
}

控制反转容器的几种写法

直接注入依赖类对象

1
2
3
4
5
class Service {}
class Controller {
constructor(service: Service) {}
setService(service: Service) {}
}

定义依赖接口, 注入实现接口的子类.

1
2
3
4
5
6
interface Service {}
class NtService extends Service {}
class Controller {
constructor(service: Service) {}
setService(service: Service) {}
}

参考文档

Spring IoC有什么好处呢Mingqi 的回答.

Donate - Support to make this site better.
捐助 - 支持我让我做得更好.