跳转到内容

理解依赖注入

发布于:
什么是依赖关系

你有一个用户类,一个帖子类,一个页面类

每当创建帖子或者页面时,都需要用户类(因为要检查创建页面或者帖子的用户是否在数据库中,并关联二者)

那么在创建帖子或者页面时,你就需要用户类这个依赖项

哦豁,那理论上每次创建帖子或者页面的时候都要随时新建一个用户类了

听上去一下子就变得恶心起来了,因为都让你耦合完了,性能什么的也不用考虑,因为卡爆了

class User {
  constructor() {
    console.log("User was instantiated");
  }
  public name = "wx";
}
class Post {
  constructor(private user = new User()) {
    console.log("Post was instantiated");
  }
}
class Page {
  constructor(private user = new User()) {
    console.log("Page was instantiated");
  }
}

//client code
const post = new Post();
const page = new Page();
[LOG]: "User was instantiated"
[LOG]: "Post was instantiated"
[LOG]: "User was instantiated"
[LOG]: "Page was instantiated"

不过我们有无需注入的依赖关系方法,也就是依赖注入

依赖注入

对的,我生来就是干这个的

不用new创建实例,一手反转控制,只要创建一个实例就可以掌控所有东西,ts可以这么干

class User {
  constructor() {
    console.log("User was instantiated");
  }
  public name = "wx";
}

class Post {
  constructor(private user: User) {
    console.log("Post was instantiated");
    console.log(this.user);
  }
}

class Page {
  constructor(private user: User) {
    console.log("Page was instantiated");
  }
}

//nestjs
const user = new User();

//client code
const post = new Post(user);
const page = new Page(user);
[LOG]: "User was instantiated"
[LOG]: "Post was instantiated"
[LOG]: User: {
  "name": "wx"
}
[LOG]: "Page was instantiated"

这下只实例一次了

nest里的依赖注入

好就好在解耦又方便测试,还有可重用性

那么模块是如何封装这些不同的类,注入依赖呢?

首先理解一件事在nest中,Module是最高指挥官,他将所有提供的程序封装其中(service controller customer class)

这意味着Module是决定某项特定服务是否导出或者被别人使用。因此,在一个特定模块内写入的所有内容都将保留在一个模块内,由你决定是否共享。比如

classDiagram
   User Module <|-- 决定
    Post Module <|-- 决定
    class User Module{
        User Controller
        User Service
        Custom Class
    }
    class Post Module{
        Post Controller
        Post Service
        Custom Class
    }
    class 决定{
        导出?
        提供?
 }

你希望User Controller使用User Service你必须让UserModule允许

在其组件内共享服务或任何其他自定义类被称为 提供(provider)

其实也就是module里的exportsproviders罢了

那么模块内依赖注入分为以下三步

1.声明一个可注入的类

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

这就包含可注入装饰器的类就是提供者了

2.然后你得让module知道有这么个东西

//app.module.ts
@Module({
  imports: [UserModuler],
  controllers: [AppController],
  providers: [AppService], //这一行
})
export class AppModule {}

3.再别的地方用,两种方法,一种是构造方法,一种是属性依赖

constructor(private readonly appService: AppService) {}
@Inject(BService)
private  appService:AppService;