依赖注入与模块
依赖注入与模块

Service
我们可以自己实现一个名叫 CatsService
的
export interface Cat {
name: string;
age: number;
breed: string;
}
@Injectable()
export class CatsService {
private readonly cats: Cat[] = [];
create(cat: Cat) {
this.cats.push(cat);
}
findAll(): Cat[] {
return this.cats;
}
}
有了
@Controller("cats")
export class CatsController {
constructor(private readonly catsService: CatsService) {}
// 等同于
private readonly catsService: CatsService;
constructor(catsService: CatsService) {
this.catsService = catsService;
}
@Post()
async create(@Body() createCatDto: CreateCatDto) {
this.catsService.create(createCatDto);
}
@Get()
async findAll(): Promise<Cat[]> {
return this.catsService.findAll();
}
}
你能发现
- 其一,
Controller 和Service 的职责边界很清晰,不存在灰色地带; - 其二,各自只关注自身职责涉及的功能,比方说
Service 通常来写业务逻辑,但它也仅仅只与业务相关。
当然你可能会觉得这很理想,时间长了增加了诸如缓存、验证等逻辑后,代码最终会变得无比庞大而难于维护。事实上这也是一个框架应该考虑和抽象出来的,后续
Providers
注入作用域
自定义的Providers
可选的Providers
有时候,你可以会需要一个依赖,但是这个依赖并不需要一定被容器解析出来。比如我们通常会传入一个配置对象,但是如果不传会使用一个默认值代替。可以使用
@Injectable()
export class HttpService<T> {
constructor(
@Optional()
@Inject("HTTP_OPTIONS")
private readonly httpClient: T
) {}
}
基于属性的注入
前面我们提过了
@Injectable()
export class HttpService<T> {
@Inject("HTTP_OPTIONS")
private readonly httpClient: T;
}
注册Provider
一般来讲控制器就是
@Module({
controllers: [CatsController],
providers: [CatsService]
})
export class ApplicationModule {}
模块
模块(Module)是一个使用了

每个应用都至少有一个根模块,根模块就是
名称 | 功能 | |
---|---|---|
providers |
可以被 |
|
controllers |
这个模块需要用到的控制器集合 | |
imports |
引入的其它模块集合 | |
exports |
此模块提供的 |
模块默认会封装
功能模块
使用下面的代码可以将相关的控制器和
@Module({
controllers: [CatsController],
providers: [CatsService]
})
export class CatsModule {}
共享的模块
在

模块都是共享的,我们可以通过导出当前模块的指定
@Module({
controllers: [CatsController],
providers: [CatsService],
exports: [CatsService] // 导出
})
export class CatsModule {}
全局模块
当一些模块在你的应用频繁使用时,可以使用全局模块来避免每次都要调用的问题。
@Global()
@Module({
controllers: [CatsController],
providers: [CatsService],
exports: [CatsService]
})
export class CatsModule {}
@Injectable()
export class ConfigService {}
@Global()
@Module({
providers: [
{
provide: ConfigService,
useValue: new ConfigService()
}
],
exports: [ConfigService]
})
export class ConfigModule {}
@Module({
imports: [ConfigModule, FeatureModule],
controllers: [AppController],
providers: [AppService]
})
export class AppModule {}
在其他的模块服务中,我们可以直接依赖于该服务:
@Injectable()
export class FeatureService {
constructor(private readonly configService: ConfigService) {}
}
动态模块
import { Module, DynamicModule } from "@nestjs/common";
import { createDatabaseProviders } from "./database.providers";
import { Connection } from "./connection.provider";
@Module({
providers: [Connection]
})
export class DatabaseModule {
static forRoot(entities = [], options?): DynamicModule {
const providers = createDatabaseProviders(options, entities);
return {
module: DatabaseModule,
providers: providers,
exports: providers
};
}
}
模块的静态方法