0
点赞
收藏
分享

微信扫一扫

Nestjs的Provider 和依赖注入


前言

上文介绍了如何理解依赖注入和控制反转,简单来说,控制反转是一种设计模式,可以将类与类的关系解耦,将人工维护转移给一个容器维护。要实现控制反转,依赖注入是一个常用方案,将依赖注册到 DI 容器中,哪里用到,就让容器将实例注入到哪里。

Nest 中的依赖注入,主要就是围绕提供者(Provider)展开。所谓的依赖,指的就是提供者类。本文通过一个简单示例,来演示 Nest 中的依赖注入是如何工作的(不涉及实现原理),主要分为三个步骤:

  1. 定义提供者
  2. 注册提供者
  3. 使用提供者

定义提供者

从代码上看,Nest 中的提供者 Provider,就是一个应用了 @Injectable() 装饰器的类,比如:

import { Injectable } from '@nestjs/common';

@Injectable() 
export class UserService { // UserService 类就是一个提供者
    findAllUsers() {
        // ......
    }
}

@Injectable() 装饰器的作用就是将提供者(比如这里的 UserService)作为依赖注册到 DI 容器中。之后当需要用到此提供者时,由 DI 容器负责完成实例化,并注入到需要的类中,从而将类与类之间的关系解耦。

注册提供者

上面只是定义了一个提供者,要使用提供者,还需要注册提供者。在一个模块定义中,比如 UserModule,在 @Module() 装饰器的 providers 属性中注册。

import { Module } from '@nestjs/common';
import { UserService } from './user.service';
import { UserController } from './user.controller';

@Module({
  providers: [UserService],
  controllers: [UserController]
})
export class UserModule {}

providers 属性是注册提供者的列表,Nest 注入器或者说是DI 容器会将这里的提供者进行实例化, 并且这些提供者在该模块内都是可共享的。

这里的 providers 其实是一种简写形式,完整的写法是:

providers: [
  {
    provide: UserService,
    useClass: UserService,
  },
];

provide 属性的值是一个标识符(inject token),DI 容器使用这个 token 来标识注册的提供者,在使用时也是根据此 token 来找到提供者。默认的话,如果只传了一个提供者的类,则 token 的值就是这个类。这一点很重要。

使用提供者

从提供者所发挥的作用上看,它就是能对外提供一些方法的类,供其他类使用。比如上面定义的 UserService,它的作用就是提供一些操作用户的逻辑,在 UserController 控制器类中使用:

import { Controller, Get } from '@nestjs/common';
import { UserService } from './user.service';

@Controller('users')
export class UserController {
  constructor(private userService: UserService) {}

  @Get()
  async getAllUsers() {
    return this.userService.findAllUsers();
  }
}

上面的示例中,在 UserController 类中要使用 UserService 类中的方法,无需自己实例化,而是在构造函数中使用了一个类型标识:

constructor(private userService: UserService) {}

Nest 的 DI 容器就能根据 “UserService” 找到此依赖项,也就是在模块定义中注册的提供者 UserService 类,然后创建实例并返回给构造函数使用。这就是依赖注入,同时这也实现了 UserController 类和 UserService 类之间的解耦,交给由 DI 容器去维护。

总结

上述的过程,就是 Nest 中一个完整的依赖注入的过程,总结一下就是:

  • 使用 @Injectable() 装饰器将一个类定义为提供者
  • 在模块类中的 @Module() 中使用 providerss注册提供者
  • 在控制器中的构造函数中,通过注册提供者时的 token ,DI 容器将找到的提供者实例返回

如果有描述不准确之处,欢迎在评论区指出,感谢阅读。

举报

相关推荐

0 条评论