没有合适的资源?快使用搜索试试~ 我知道了~
Nestjs模块机制的概念和实现原理.doc
1.该资源内容由用户上传,如若侵权请联系客服进行举报
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
版权申诉
0 下载量 20 浏览量
2022-07-09
22:41:22
上传
评论
收藏 1020KB DOC 举报
温馨提示
试读
12页
Nestjs模块机制的概念和实现原理.doc
资源推荐
资源详情
资源评论
Nestjs 模块机制的概念和实现原理
1 前言
Nest 提供了模块机制,通过在模块装饰器中定义提供者、导入、导出和提供者构造函数
便完成了依赖注入,通过模块树组织整个应用程序的开发。按照框架本身的约定直接撸一个
应用程序,是完全没有问题的。可是,于我而言对于框架宣称的依赖注入、控制反转、模块、
提供者、元数据、相关装饰器等等,觉得缺乏一个更清晰系统的认识。
为什么需要控制反转?
什么是依赖注入?
装饰器做了啥?
模块 (@Module) 中的提供者(providers),导入(imports)、导出(exports)是什么实现原理?
好像能够理解,能够意会,但是让我自己从头说清楚,我说不清楚。于是进行了一番探索,
便有了这篇文章。从现在起,我们从新出发,进入正文。
2 两个阶段
2.1 Express、Koa
一个语言和其技术社区的发展过程,一定是从底层功能逐渐往上丰富发展的,就像是树根
慢慢生长为树枝再长满树叶的过程。在较早,Nodejs 出现了 Express 和 Koa 这样的基本 Web
服务框架。能够提供一个非常基础的服务能力。基于这样的框架,大量的中间件、插件开始
在社区诞生,为框架提供更加丰富的服务。我们需要自己去组织应用依赖,搭建应用脚手架,
灵活又繁琐,也具有一定工作量。
发展到后面,一些生产更高效、规则更统一的框架便诞生了,开启了一个更新的阶段。
2.2 EggJs、Nestjs
为了更加适应快速生产应用,统一规范,开箱即用,便发展出了 EggJs、NestJs、Midway
等框架。此类框架,通过实现底层生命周期,将一个应用的实现抽象为一个通用可扩展的过
程,我们只需要按照框架提供的配置方式,便可以更简单的实现应用程序。框架实现了程序
的过程控制,而我们只需要在合适位置组装我们的零件就行,这看起来更像是流水线工作,
每个流程被分割的很清楚,也省去了很多实现成本。
2.3 小结
上面的两个阶段只是一个铺垫,我们可以大致了解到,框架的升级是提高了生产效率,而
要实现框架的升级,就会引入一些设计思路和模式,Nest 中就出现了控制反转、依赖注入、
元编程的概念,下面我们来聊聊。
3 控制反转和依赖注入
3.1 依赖注入
一个应用程序实际就是非常多的抽象类,通过互相调用实现应用的所有功能。随着应用代
码和功能复杂度的增加,项目一定会越来越难以维护,因为类越来越多,相互之间的关系越
来越复杂。
举个例子,假如我们使用 Koa 开发我们的应用,Koa 本身主要实现了一套基础的 Web
服务能力,我们在实现应用的过程中,会定义很多类,这些类的实例化方式、相互依赖关系,
都会由我们在代码逻辑自由组织和控制。每个类的实例化都是由我们手动 new,并且我们
可以控制某个类是只实例化一次然后被共享,还是每次都实例化。下面的 B 类依赖 A,每
次实例化 B 的时候,A 都会被实例化一次,所以对于每个实例 B 来说,A 是不被共享的
实例。
class A{}
// B
class B{
contructor(){
this.a = new A();
}
}
下面的 C 是获取的外部实例,所以多个 C 实例是共享的 app.a 这个实例。
class A{}
// C
const app = {};
app.a = new A();
class C{
contructor(){
this.a = app.a;
}
}
下面的 D 是通过构造函数参数传入,可以每次传入一个非共享实例,也可以传入共享的
app.a 这个实例(D 和 F 共享 app.a),并且由于现在是参数的方式传入,我也可以传入一个
X 类实例。
class A{}
class X{}
// D
const app = {};
app.a = new A();
class D{
contructor(a){
this.a = a;
}
}
class F{
contructor(a){
this.a = a;
}
}
new D(app.a)
new F(app.a)
new D(new X())
这种方式就是依赖注入,把 B 所依赖的 A,通过传值的方式注入到 B 中。通过构造函
数注入(传值)只是一种实现方式,也可以通过实现 set 方法调用传入,或者是其他任何
方式,只要能把外部的一个依赖,传入到内部就行。其实就这么简单。
class A{}
// D
class D{
setDep(a){
this.a = a;
}
}
const d = new D()
d.setDep(new A())
3.2 All in 依赖注入?
随着迭代进行,出现了 B 根据不同的前置条件依赖会发生变化。比如,前置条件一
this.a 需要传入 A 的实例,前置条件二 this.a 需要传入 X 的实例。这个时候,我们就会开
始做实际的抽象了。我们就会改造成上面 D 这样依赖注入的方式。
初期,我们在实现应用的时候,在满足当时需求的情况下,就会实现出 B 和 C 类的写
法,这本身也没有什么问题,项目迭代了几年之后,都不一定会动这部分代码。我们要是去
考虑后期扩展什么的,是会影响开发效率的,而且不一定派的上用场。所以大部分时候,我
们都是遇到需要抽象的场景,再对部分代码做抽象改造。
// 改造前
class B{
contructor(){
this.a = new A();
}
}
new B()
// 改造后
class D{
contructor(a){
剩余11页未读,继续阅读
资源评论
书博教育
- 粉丝: 1
- 资源: 2835
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功