前言
最近在学习 Nest,所以想要做一个学习记录来督促自己进行学习,也是因为自己记性很差,所以要手写点东西来增强记忆。同时也是希望有人能对我的文章提点意见,让我能加深该方面知识的理解吧
一 对象
- Controller 对象: 接收 http 请求,调用 Service, 返回响应
- Service 对象: 实现业务逻辑
- Repository 对象: 实现对数据库的增删改查
- DataSource 对象: 数据库链接对象
- Config 对象: 配置对象
这些对象有着相互依赖的关系
- Controller 依赖 Service 实现业务逻辑
- Service 依赖 Repository 来做增删改查
- Repository 依赖 DataBase 来建立链接
- Database 从 Config 中拿去用户名 | 密码等配置信息
以下则是各个对象的创建顺序
// 1. 配置对象
const config = new Config({ username: 'xxx, password: 'xxx' })\
// 2. 数据库链接对象
const database = new DataSource(config)
// 3. 存储对象
const repository = new Repository(database)
// 4. 业务逻辑对象
const service = new Service(repository)
// 5. 请求响应对象
const controller = new Controller(service)
二 定义
从上一个篇章中,我们可以知道,面向对象的设计系统中,它的底层都是有N个对象构成的,各个对象之间通过相互合同,最终实现系统的业务逻辑. 但是如果有大量的对象,并且这些对象直接同时有复杂的多重依赖关系,那么就会出现一个严重的问题,那就是高耦合-如何一个对象出现问题,那么其他对象甚至整个系统都会被影响到.
而 IOC (Inversion of Control 控制反转)的存在就是为这个问题提供了一种解决思路
1 什么是 IOC
简单的来讲, IOC 就是在对象和对象之间插入了一个容器,就像是两个小齿轮中的大齿轮,起着是两个小齿轮一起转动的效果,把两个小齿轮"链接"在一起.
而如果没有这个大齿轮,那么两个小齿轮之间就没有任何联系,这样两个小齿轮的依赖关系就降到了最低,解决了高耦合的问题.
2 IOC(控制反转) 和 DI(依赖注入)
1) IOC
本来一个对象想要获取另一个对象时,我们往往会 new 一个对象出来,去手动创建一个对象来获取该对象中的数据和方法.
但是现在我们通过 IOC 容器直接在 class 上声明该对象依赖了什么对象,然后让工具自己去分析依赖关系,在根据前后关系创建依赖,并进行组装.
实现了创建对象A时,主动把该对象A依赖的对象B之间注入到该对象A中去,不再需要手动创建.
而这种对象A获得依赖对象B的过程,由主动创建变成了被动注入的行为,控制权从A移交到了容器中,所以这里方式就叫做 "控制反转"
2) DI (Dependency Injection)
依赖注入就是 IOC 容器在运行期间,动态的将某种依赖关系注入到对象之中
3) 总结
简单的来讲, IOC 就是解决对象之间解耦的思路,而 DI 则是该思路的实现方式
三 使用 (nest)
1) 基本使用
在 java 和 nest 中,都会使用装饰器(注解)的形式在 class 上进行依赖的声明.
Injectable() 就代表了可注入,将该 class 放入到了 IOC 容器中去,而
@InjectRepository() 则是该 class 需要的依赖
2) 不同装饰器的定义
- @Injectable()
- 代表着既可以被注入(注入其他依赖),同时也可以被注入(被其他对象依赖)
- 所以 service 使用该装饰器
- @Controller()
- 代表着只能被注入(注入其他依赖)
- 所以 controller 使用该装饰器
- @Module()
- 用于处理依赖关系,定义模块的 controller | providers | imports | exports 等
- controller 代表控制器,就是被 @Controller 装饰的类
- providers 代表着可以被注入,也可以注入到其他对象,比如这里的 PersonService | AppService
- **exports **导出 providers, 将该业务的方法暴露出去,给其他业务使用
- imports 引入其他业务的模块,使用其他业务中的方法
四 优缺点
1) 优点
2) 缺点
- 生成对象的步骤变得更加复杂了
- 工程成本相对较大
- 在运行效率上可能会有一定影响