高瀬博道の技術ブログ

高瀬博道の技術ブログです。

もう2023年になったので、今さらNestJSに入門しようと思う - その20

前回

takasehiromichiex.com

DIの基礎

依存性注入は、依存関係のインスタンス化を独自のコードで強制的に行うのではなく、IoCコンテナ、つまりNestJSランタイムシステムに移譲する制御の反転手法です。

まず、@Injectable()デコレータは、クラスをプロバイダとしてマークします。そのため、このデコレータがつけられたクラスは、Nest IoCコンテナで管理できるクラスになります。

src/cats/cats.service.ts
import { Injectable } from '@nestjs/common';
import { Cat } from './cats.interface';

@Injectable()
export class CatsService {
    private readonly cats: Cat[] = [];

    create(cat: Cat) {
        this.cats.push(cat);
    }
    findAll(): Cat[] {
        return this.cats;
    }
}

次に、プロバイダをコントローラクラスに挿入しています。コンストラクタで宣言します。

src/cats/cats.controller.ts
import { Body, Controller, Get, Post, UseInterceptors } from "@nestjs/common";
import { CreateCatDto } from "src/dto/cat/cat.dto";
import { Cat } from "./cats.interface";
import { CatsService } from "./cats.service";
import { ValidationPipe } from "../pipe/validation/validation.pipe";
import { User } from "src/decorator/user/user.decorator";

@Controller("cats")
export class CatsController {
  constructor(private catsService: CatsService) {}

  @Post()
  create(@Body(new ValidationPipe()) createCatDto: CreateCatDto) {
    this.catsService.create(createCatDto);
  }
  @Get()
  findAll(): Cat[] {
    return this.catsService.findAll();
  }

  @Get("abc")
  async findOne(@User() user: any): Promise<void> {
    console.log(user);
  }
}

最後に、プロバイダをNest IoCコンテナに登録しています。

src/cats/cats.module.ts
import { Module } from '@nestjs/common';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';

@Module({
  controllers: [CatsController],
  providers: [CatsService]
})
export class CatsModule {}

Nest IoCコンテナがコントローラをインスタンス化するとき、依存関係を探します。

依存関係が見つかると、サービスのトークンを探し始めます。

これにより、サービスクラスが返されます。

シングルトンスコープだと、Nestはサービスのインスタンスを作成してキャッシュしてから返すか、すでにキャッシュされている場合は既存のインスタンスを返します。

標準プロバイダ

@Module()デコレータを詳しくみていきます。

src/cats/cats.module.ts
import { Module } from '@nestjs/common';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';

@Module({
  controllers: [CatsController],
  providers: [CatsService]
})
export class CatsModule {}

providersは、実は以下のようになります。

src/cats/cats.module.ts
import { Module } from "@nestjs/common";
import { CatsController } from "./cats.controller";
import { CatsService } from "./cats.service";

@Module({
  controllers: [CatsController],
  providers: [
    {
      provide: CatsService,
      useClass: CatsService,
    },
  ],
})
export class CatsModule {}

実のところ、providers: [CatsService]は省略形です。

これは、CatsServiceというトークンを、CatsServiceというクラスに関連づけています。

まとめ

ここまでで、

  • DIの基礎について
  • 標準プロバイダについて

を学びました。

次回は、もう少しカスタムプロバイダを掘り下げようと思います。

コード

今回のコードは、以下に格納しました。

github.com

takasehiromichiex.com