Dependency injection 注入vs可注入vs自定义提供程序
我很难弄清楚什么时候该用什么。我了解DI,并且已经做了很多年了,但是在NestJS中,文档中似乎缺少了一些东西,这有助于我理解为什么注入项中缺少一些指定属性 我们有一个通过自定义提供程序注入的记录器 通过查看文档,他们会在构造函数区域添加Dependency injection 注入vs可注入vs自定义提供程序,dependency-injection,nestjs,Dependency Injection,Nestjs,我很难弄清楚什么时候该用什么。我了解DI,并且已经做了很多年了,但是在NestJS中,文档中似乎缺少了一些东西,这有助于我理解为什么注入项中缺少一些指定属性 我们有一个通过自定义提供程序注入的记录器 通过查看文档,他们会在构造函数区域添加@Inject,但是如果我是通过自定义提供程序进行注入,为什么要使用@Inject 同样,如果我们有自定义提供程序处理模块的所有注入设置,为什么要使用@Injectable 出现的问题是,文件名在其他注入服务中丢失,有时当记录器在一个服务中执行时,文件名是相同的
@Inject
,但是如果我是通过自定义提供程序进行注入,为什么要使用@Inject
同样,如果我们有自定义提供程序处理模块的所有注入设置,为什么要使用@Injectable
出现的问题是,文件名在其他注入服务中丢失,有时当记录器在一个服务中执行时,文件名是相同的,而在其他时间,服务不同,它将保留来自不同服务的ctor名称的文件名
不管怎么说,我不明白为什么要用一套来代替另一套
更新:我发现我们在某些服务上遵循生命周期,但我发现记录器在执行时没有保留
//custom-provider
export ClientProvider = {
provide: Client,
userFactory: (logger: Logger): Client => {
return new Client(logger);
},
inject: [Logger.getToken()]
};
//client
export class Client{
private readonly logger;
constructor(logger:Logger){
this.logger = logger;
if (this.logger) this.logger.fileName = this.constructor.name;
}
}
//logger
export class Logger {
static getToken(): string { return 'the-token-key'; }
private filename: string;
constructor(filename: string){
this.filename = filename;
}
}
//cat-service
export class CatService implements OnModuleInit {
private readonly logger;
constructor(@Inject(Logger.getToken()) private logger:Logger){
this.logger = logger;
}
onModuleInit() {
if (this.logger) this.logger.fileName = this.constructor.name;
}
}
所以,在高层,Nest自然地使用从Typescript反射的元数据来知道绑定什么和绑定到哪里。通常,这种元数据类似于运行时存在的类名,这就是为什么不能使用接口
@Injectable()
告诉Nest它应该查找此类构造函数中提供的元数据,并找到正确的提供程序。正如前面提到的,这就是Nest执行大部分DI的方式
@Inject()
告诉Nest,“嘿,我知道这说明它是一个记录器
类,但实际上是用我告诉您的注入令牌向提供者注入”,这对于使用记录器类的特定实例等非常有用
对于自定义提供程序,@Injectable()
在您使用工厂时是不必要的,如您所示,但如果您使用类来代替,则是必要的,因为工厂返回要提供的值的实例,而对于useClass
,您返回的是Nest需要实例化的类定义
我能看到您的文件名被覆盖的唯一原因是,提供程序是模块之间的单例作用域,但是如果同一个提供程序在
提供程序数组中,那么每次都应该是一个新实例,所以可能有点不稳定谢谢@Jay!我想得更多了,我忘了单身汉。另外,谢谢你的解释,它真的帮助了我。让我问你:令牌只是命名配置吗?例如,如果您有多个相同类的设置,令牌可以帮助您保持唯一性以供注入?这绝对是一个很好的方法。对于我目前正在构建的系统,我有一个自定义装饰器,可以接受参数。这个decorator本质上是嵌套的@Inject()
decorator的包装器,它有助于创建正确的注入令牌。此令牌由decorator和动态模块的forFeature()
函数创建,以确保为当前上下文正确创建提供程序令牌。