首页 > 其他分享 >【NestJS系列】DI依赖注入与IOC控制反转

【NestJS系列】DI依赖注入与IOC控制反转

时间:2023-07-17 10:33:22浏览次数:38  
标签:AppService 依赖 DI Nest NestJS import IOC 注入

前言

上篇文章我们学习了如何使用nest-cli来快速生成一个NestJS后端项目,当我们打开编辑器查看代码时,会发现整个代码风格有点类似JAVA的spring框架,并且你会发现一些service类在controller控制器的constructor中注入后,可以不需要手动new就可以直接使用该类对应的实例方法。

比如:

import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get('/hello')
  get(): string {
    return this.appService.getHello();
  }
}

这其实就是Nest依赖注入与控制反转,目的主要是方便代码之间的解耦从而减少维护成本。

什么是依赖注入(DI)与控制反转(IOC)

这两个概念不要搞混了,IOC其实是面向对象编程中的一种设计模式,而DI则是为了实现IOC的一种技术。

传统耦合代码

比如,我们有两个类,它们之间存在耦合关系,我们一般会这样写:

// A.ts
class A {
  name: string
  constructor(name: string) {
    this.name = name
  }
}

// B.ts
class B {
  age: number
  name: A
  constructor(age: number) {
    this.age = age
    this.name = new A('南玖')
  }
}

// main.ts
const b = new B(18)
console.log(b)

当我们遇到类与类之间存在依赖关系时,一般会直接在类的内部创建依赖对象,这样就会导致各个类之间形成耦合,并且这种关系会随着依赖关系越来越复杂从而耦合度也会越来越高,最终造成代码的难以维护。

简易版IOC

为了解决上面代码带来的耦合性问题,我们可以使用IOC容器来进行管理

// container.ts
export class Container {
  modules = new Map()
  
  // 注册实例
  provide(key: string, clazz: any, argvs: Array<any>) {
    this.modules.set(key, {clazz, argvs})
  }
  // 获取实例
  get(key: string) {
    const {clazz, argvs} = this.modules.get(key)
    return Reflect.construct(clazz, argvs)
  }
}

这里的Reflect.construct是为了帮我们实例化一个对象。

以上就是容器化思路,统一管理,可以实现类与类之间的解耦。

Nest JS的IOC与DI

依赖注入是一种控制反转IOC(inversion of control)技术,就是你可以把对象或依赖的实例化交给IOC容器去处理,在NestJS中这个容器就是NestJS的运行时系统。当需要一个对象实例的时候,我们不需要自己手动new xxxClass(),只需要在合适的地方对类进行注册,在需要用到的地方直接注入,容器将为我们完成new的动作

Nest中使用依赖注入一般有以下三步:

声明定义

使用@Injectable装饰器来声明一个类,它表示该类可以由NestIOC容器管理

// app.service.ts
import { Injectable } from '@nestjs/common';

@Injectable()
export class AppService {
  getHello(): string {
    return 'Hello nanjiu';
  }
}

声明在什么地方使用

这是依赖注入的地方,一般是在类的构造函数constructor中注入,只有完成注入后才可以使用

// app.controller.ts
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get('/hello')
  get(): string {
    return this.appService.getHello();
  }
}

官方把appService称为tokenNestJS会根据这个token在容器中找到第1步中声明的类(这个对应关系将在第三步中进行关联注册),从而提供对应的实例,这里的实例全局唯一,只有1个!在第一次需要该实例的时候,Nestnew一个出来,而后会缓存起来,后序如果其它地方也注入了这个依赖,那Nest会从缓存中拿到之前new出来的实例供大家使用。

建立注入依赖与容器中类的联系

依赖注入后还需要在Module中进行关联

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

Nest会根据所有注入的依赖关系生成一个依赖关系图,就有点类似我们使用import引入各个模块时也会生成一个复杂的依赖关系图。这里AppController中依赖了AppService,如果AppService中还依赖其它东西也会一并放到Nest构建的依赖关系图中,Nest会从下到上按照依赖顺序构建出一整张依赖关系图保证所有的依赖关系正常运作。

标签:AppService,依赖,DI,Nest,NestJS,import,IOC,注入
From: https://www.cnblogs.com/songyao666/p/17559312.html

相关文章

  • Redis多级缓存
    什么是多级缓存传统缓存的问题传统的缓存在请求到达Tomcat后,先查询Redis,如果未命中则查询数据库,存在以下问题:请求要经过Tomcat处理,Tomcat的性能成为整个系统的瓶颈Redis缓存失效时,会对数据库产生冲击多级缓存就是充分利用请求处理的每个环节,分别添加缓存,减轻Tomcat压力,提......
  • nvidia驱动安装和升级
    安装GPU驱动之前建议升级内核,这里踩坑了!!!英伟达驱动官网下载链接:https://www.nvidia.cn/Download/index.aspx?lang=cn安装gpu驱动安装相关依赖,需安装kernel-headeryuminstallkernel-develgcc-y检查内核版本是否一致ls/boot|grepvmlinurpm-aq|grep......
  • redis序列化配置
    redis序列化配置@ConfigurationpublicclassRedisTemplateConfiguration{/***@paramredisConnectionFactory*@return*/@BeanpublicRedisTemplate<Object,Object>redisTemplate(RedisConnectionFactoryredisConnectionFactory){......
  • Python【3】有序字典 OrderdDict
    有序字典可以按字典中元素的插入顺序来输出。参考https://www.cnblogs.com/lowmanisbusy/p/10257360.htmlimportcollectionsmy_order_dict=collections.OrderedDict()my_order_dict["name"]="lowman"my_order_dict["age"]=45my_order_dict["money&......
  • Codeforces Round 883 (Div. 3)
    只写部分题目。A.RudolphandCuttheRope#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongconstintN=2e5+5;intt,n,a[N],b[N];signedmain(){ cin>>t; while(t--){ cin>>n; intres=0; for(inti=......
  • 如何在.NET Core中使用redis
    一、1.添加Redis依赖项:在.NETCore项目中,你需要添加对StackExchange.Redis库的引用。你可以通过NuGet包管理器或手动添加依赖项来完成此操作。2. 配置Redis连接:在appsettings.json文件中,添加Redis连接配置。例如:"Redis":{"ConnectionString":"localhost:6379"}3.......
  • 记录一次.net core使用redis报错
    一、记录一次报错:报错信息如下RedisTimeoutException:Timeoutawaitingresponse(outbound=0KiB,inbound=1KiB,12063mselapsed,timeoutis1000ms),command=SCAN,next:SCAN,inst:0,qu:0,qs:1,aw:False,bw:Inactive,rs:DequeueResult,ws:Idle,in:0,in-......
  • AI绘画StableDiffusion实操教程:冰霜旗袍美女
    飞书原文链接,获取更多资源:AI绘画StableDiffusion实操教程:冰霜旗袍美女前几天分享了StableDiffusion的入门到精通教程:AI绘画:StableDiffusion终极炼丹宝典:从入门到精通但是还有人就问:安装是安装好了,可是为什么生成的图片和你生成的图片差距那么远呢?怎么真实感和质感一个天一个......
  • redis keys *
    RedisKeys命令的使用及示例在Redis中,Keys命令用于获取满足指定模式的key列表。它是一个非常有用的命令,可以用来查找和操作Redis中的key。本文将介绍RedisKeys命令的使用方法,并提供一些代码示例帮助读者更好地理解和使用该命令。RedisKeys命令的语法RedisKeys命令的基本语法......
  • redis insight
    如何实现RedisInsight简介在这篇文章中,我将教你如何实现RedisInsight。RedisInsight是一个开源的Web界面,用于可视化和管理Redis数据库。它提供了一个友好的用户界面,让你可以方便地查看和操作Redis数据库。流程概述下面是实现RedisInsight的大致流程:步骤描述1......