Nest 的 IoC 机制

后端系统中,会有很多对象:

  • Controller 对象:接收 http 请求,调用 Service,返回响应

  • Service 对象:实现业务逻辑

  • Repository 对象:实现对数据库的增删改查

此外,还有数据库链接对象 DataSource,配置对象 Config 等等。

这些对象有着错综复杂的关系:

Controller 依赖了 Service 实现业务逻辑,Service 依赖了 Repository 来做增删改查,Repository 依赖 DataSource 来建立连接,DataSource 又需要从 Config 对象拿到用户名密码等信息。

这就导致了创建这些对象是很复杂的,你要理清它们之间的依赖关系,哪个先创建哪个后创建。

比如这样:

const config = new Config({ username: 'xxx', password: 'xxx'});const dataSource = new DataSource(config);const repository = new Repository(dataSource);const service = new Service(repository);const controller = new Controller(service);

要经过一系列的初始化之后才可以使用 Controller 对象。

而且像 config、dataSource、repository、service、controller 等这些对象不需要每次都 new 一个新的,一直用一个就可以,也就是保持单例。

在应用初始化的时候,需要理清依赖的先后关系,创建一大堆对象组合起来,还要保证不要多次 new,是不是很麻烦?

没错,这是一个后端系统都有的痛点问题。

解决这个痛点的方式就是 IoC(Inverse of Control)。

java 的 Spring 就实现了 IoC,Nest 也同样实现了。

那什么是 IoC 呢?

之前我们手动创建和组装对象不是很麻烦么,我能不能在 class 上声明依赖了啥,然后让工具去分析我声明的依赖关系,根据先后顺序自动把对象创建好了并组装起来呢?

比如这样声明 AppController 依赖了这两个 Service,然后让工具分析依赖自动帮我创建好这三个对象并设置依赖关系。

这就是 IoC 的实现思路。

它有一个放对象的容器,程序初始化的时候会扫描 class 上声明的依赖关系,然后把这些 class 都给 new 一个实例放到容器里。

创建对象的时候,还会把它们依赖的对象注入进去。

这样不就完成了自动的对象创建和组装么?

这种依赖注入的方式叫做 Dependency Injection,简称 DI。

而这种方案为什么叫 IoC 也很容易理解了,本来是手动 new 依赖对象,然后组装起来,现在是声明依赖了啥,等待被注入。

从主动创建依赖到被动等待依赖注入,这就是 Inverse of Control,反转控制。

在 class 上声明依赖的方式,大家都选择了装饰器的方式(在 java 里这种语法叫做注解)。

比如上面就是声明这个 class 要放到 IOC 容器里,然后它的依赖是啥。

这样 IOC 容器扫描到它就知道怎么创建它的对象了。

知道了 IOC 是啥,下面我们来看看真实的 Nest 项目里是怎么用 IoC 的:

npx nest new nest-ioc

然后进入这个目录,执行 npm run start,把服务跑起来:

 浏览器访问 http://localhost:3000 就可以看到 nest 服务返回的 hello world:

 我们看看代码里它是怎么创建对象的:

 它有一个 AppService 声明了 @Injectable,代表这个 class 可注入,那么 nest 就会把它的对象放到 IOC 容器里。

AppController 声明了 @Controller,代表这个 class 可以被注入,nest 也会把它放到 IoC 容器里。

AppController 的构造器参数依赖了 AppService。

或者这样通过属性的方式声明依赖:

前者是构造器注入,后者是属性注入,两种都可以。

为什么 Controller 是单独的装饰器呢?

因为 Service 是可以被注入也是可以注入到别的对象的,所以用 @Injectable 声明。

而 Controller 只需要被注入,所以 nest 单独给它加了 @Controller 的装饰器。

然后在 AppModule 里引入:

通过 @Module 声明模块,其中 controllers 是控制器,只能被注入。

providers 里可以被注入,也可以注入别的对象,比如这里的 AppService。

然后在入口模块里跑起来:

 那么 nest 就会从 AppModule 开始解析 class 上通过装饰器声明的依赖信息,自动创建和组装对象。

所以 AppController 只是声明了对 AppService 的依赖,就可以调用它的方法了:

nest 在背后自动做了对象创建和依赖注入的工作。

nest 还加了模块机制,可以把不同业务的 controller、service 等放到不同模块里。

nest g module other

会生成如下代码: 

用 nest cli 的 generate 命令生成一个模块。

会在 AppModule 里自动 imports 这个模块:

 

当 import 别的模块后,那个模块 exports 的 provider 就可以在当前模块注入了。

比如我们再生成 OtherService:

并自动添加到 OtherModule 的 providers 中:

 我们改下 OtherService,添加一个方法:

然后在 OtherModule 里 exports: 

那当 AppModule 引用了 OtherModule 之后,就可以注入它 exports 的 OtherService 了。

 

 我们在 AppService 里注入下:

 把服务跑起来:

npm run start:dev

浏览器访问下,可以看到 AppModule 的 AppService 调用 OtherModule 的 OtherService 成功了:

 这就是 Nest 的 IoC 机制。

总结

后端系统有很多的对象,这些对象之间的关系错综复杂,如果手动创建并组装对象比较麻烦,所以后端框架一般都提供了 IoC 机制。

IoC 机制是在 class 上标识哪些是可以被注入的,它的依赖是什么,然后从入口开始扫描这些对象和依赖,自动创建和组装对象。

Nest 里通过 @Controller 声明可以被注入的 controller,通过 @Injectable 声明可以被注入也可以注入别的对象的 provider,然后在 @Module 声明的模块里引入。

并且 Nest 还提供了 Module 和 Module 之间的 import,可以引入别的模块的 provider 来注入。

虽然 Nest 这套实现了 IoC 的模块机制看起来繁琐,但是却解决了后端系统的对象依赖关系错综复杂的痛点问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/35770.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

内外网文件流转场景日益复杂,看麒麟信安如何构筑安全防线?

随着信息化快速发展,数据已成为企业核心资产,根据信息安全分级保护和等级保护的相关要求,诸多单位都采取了内外网隔离措施以确保信息安全。但在管理内外部数据流通时,用户单位在集中加密存储、文件流转管理机制、外带文件审批管理…

AI原力觉醒:华硕NUC组团出道,快来Pick属于你的NUC

NUC 家族组团出道,全新的计算体验,重新定义桌面设备。AI加持下,谁最适合你? 颜值担当 NUC 14 Pro 居家必备单品 适用于广大消费者的NUC 14 Pro,不仅颜值在线,更多方位考虑您的日常所需,工作娱…

2024/6/28 英语每日一段

The Supreme Court on Thursday rejected a challenge to an obscure provision of President Donald Trump’s 2017 tax package, ending a lawsuit that many experts feared could destabilize the nation’s tax system. In a divided decision, the court upheld a one-ti…

基于SpringBoot养老院管理系统设计和实现(源码+LW+调试文档+讲解等)

💗博主介绍:✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者,博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌💗 🌟文末获取源码数据库🌟感兴趣的可以先收藏起来,还…

Java网络编程(JavaWeb的基础)

Java网络编程(JavaWeb的基础) 文章目录 Java网络编程(JavaWeb的基础)前言一、网络编程概述1.1 软件架构&网络基础1.2 网络通信要素:IP/端口/通信协议1.3 传输层协议:tcp/udp 二、网络编程API2.1 InetAddress类2.2 Socket类&am…

控制台扫雷(C语言实现)

目录 博文目的实现思路项目创建文件解释 具体实现判断玩家进行游戏还是退出扫雷棋盘的确定地图初始化埋雷玩家扫雷的实现雷判断函数 源码game.cgame.h扫雷.c 博文目的 相信不少人都学习了c语言的函数,循环,分支那我们就可以写一个控制台的扫雷小游戏来检…

中小企业进行数字化转型会面临哪些挑战?

在当今这个信息化、数字化的时代,中小企业进行数字化转型已不再是选择,而是必然。然而,这条转型之路并非坦途,它充满了未知与挑战。今天,我们就来探讨一下中小企业为社么要进行数字化转型以及在数字化转型过程中可能遇…

1983springboot VUE兼职招聘管理系统开发mysql数据库web结构java编程计算机网页源码maven项目

一、源码特点 springboot VUE兼职招聘管理系统是一套完善的完整信息管理类型系统,结合springboot框架和VUE完成本系统,对理解JSP java编程开发语言有帮助系统采用springboot框架(MVC模式开发),系统具有完整的源代码和…

重磅!免费一键批量混剪工具它来了,一天上万短视频不是梦

很多做短视频营销的朋友需要批量生成大量的短视频,但是市面上的工具一是不好用,二是要收费。 今天给大家介绍一款免费的,可以自动化批量生成短视频的工具MoneyPrinterPlus。 同时支持windows和linux平台。 有了它,一天生成上万短…

从零创建深度学习张量库,支持gpu并行与自动微分

多年来,我一直在使用 PyTorch 构建和训练深度学习模型。尽管我已经学会了它的语法和规则,但总有一些东西激起了我的好奇心:这些操作内部发生了什么?这一切是如何运作的? 如果你已经到这里,你可能也有同样的…

Linux 的启动流程

第一步、加载内核 操作系统接管硬件以后,首先读入 /boot 目录下的内核文件。 以我的电脑为例,/boot 目录下面大概是这样一些文件: $ ls /bootconfig-3.2.0-3-amd64config-3.2.0-4-amd64grubinitrd.img-3.2.0-3-amd64initrd.img-3.2.0-4-amd6…

云效BizDevOps上手亲测

云效BizDevOps上手亲测 什么是云效项目协作Projex配置2023业务空间原始诉求字段原始诉求工作流创建原始诉求配置2023产品空间创建主题业务原始诉求关联主题配置2023研发空间新建需求需求关联主题 与传统区别云效开发流程传统开发流程云效BizDevOps 操作体验 什么是云效 在说到…

【vue3】【vant】 移动本草纲目案例发布收藏项目源码

更多项目点击👆👆👆完整项目成品专栏 【vue3】【vant】 移动本草纲目案例发布收藏项目源码 获取源码方式项目说明:其中功能包括 项目包含:项目运行环境文件截图 获取源码方式 加Q群:632562109项目说明&am…

揭秘搜索引擎核心机制:网页爬行、索引、预处理、建立索引、查询处理与结果排序策略的深入解读

搜索引擎的工作原理与流程是一个复杂而精细的系统工程,旨在帮助用户从互联网的海量信息中快速找到最相关、最有价值的内容。 理解搜索引擎工作原理对于内容创作、网站优化、广告投放及日常搜索至关重要。它能指导网页设计更加友好,提高搜索引擎排名&…

热点观察 | 《姜饼人王国》新作来袭、《Monopoly GO!》荣登5月全球畅销榜榜首

本周出海热点: 1. 中国品牌借欧洲杯打响知名度 2. 米哈游玩家切割二次元 3. 6月27日,Steam游戏《六月衷曲》上线TapTap 4. 《Monopoly GO!》荣登5月全球畅销榜榜首 5. 《地下城与勇士》拿下本周亚洲T1市场畅销榜冠军 6. 《姜饼人王国》新作强势登顶…

【MySQL连接器(Python)指南】07-连接器其它参数

文章目录 前言MySQL身份验证选项字符编码事务时区SQL模式错误处理客户端标志启用和禁用类型转换通过SSL连接连接池协议压缩总结前言 MySQL连接器(Python),用于让Python程序能够访问MySQL数据库。要想让Python应用程序正确高效地使用MySQL数据,就需要深入了解MySQL连接器的特性…

AI在创造还是毁掉音乐

轮番上线的音乐大模型,一举将素人生产音乐的门槛降到了最低,并掀起了音乐圈会不会被AI彻底颠覆的讨论。短暂的兴奋后,AI产品的版权归属于谁,创意产业要如何在AI的阴影下生长,都在被更多理性的目光审视。 一、整体介绍 …

pg_rman:备份和恢复管理工具#postgresql培训

pg_rman 是 PostgreSQL 的在线备份和恢复工具。 pg_rman 项目的目标是提供一种与 pg_dump 一样简单的在线备份和 PITR 方法。此外,它还为每个数据库集群维护一个备份目录。用户只需一个命令即可维护包括存档日志在内的旧备份。 #PG培训#PG考试#postgresql考试#pos…

【面试干货】静态类型的特点及其在Java中的应用

【面试干货】静态类型的特点及其在Java中的应用 1、静态类型的特点1.1 静态属性1.2 静态方法1.3 静态类 2、静态类型在Java中的应用 💖The Begin💖点点关注,收藏不迷路💖 在面向对象编程中,静态类型 是一种重要的概念&…

网传不好投了?2区Frontiers“水刊”强势回归,11天录用,十投九中!

本周投稿推荐 SSCI • 1区,4.0-5.0(无需返修,提交可录) EI • 各领域沾边均可(2天录用) CNKI • 7天录用-检索(急录友好) SCI&EI • 4区生物医学类,0.1-0.5&…