正常情况在module或者component中注入服务的写法:
providers: [LoggerService],
但是,可以将 DI 配置为使用不同的类或任何其他不同的值来与 LoggerService 类关联。因此,当注入 LoggerService 时,会改为使用这个新值。
类提供者语法是一个简写表达式,可以扩展为由 Provider 接口定义的提供者配置信息。
在这种情况下,Angular 将 providers 值展开为完整的提供者对象,如下所示:
[{ provide: LoggerService, useClass: LoggerService }]
展开后的提供者配置是一个具有两个属性的对象字面量:
-
provide属性包含一个令牌,该令牌会作为定位依赖值和配置注入器时的键。 -
第二个属性是一个提供者定义对象,它会告诉注入器如何创建依赖值。提供者定义对象中的键可以是以下值之一:
- useClass - 此选项告诉 Angular DI 在注入依赖项时要实例化这里提供的类
- useExisting - 允许你为令牌起一个别名,并引用任意一个现有令牌。
- useFactory - 允许你定义一个用来构造依赖项的函数。
- useValue - 提供了一个应该作为依赖项使用的静态值。
下面就针对 useClass useExisting useFactory useValue 这四个key做一下解释。
useClass
写法:
[{ provide: Logger, useClass: EvenBetterLogger }]
写法解读:
当在组件或任何其他类中请求 Logger 依赖项时,将转而实例化 EvenBetterLogger 类。
@Injectable({
providedIn: 'root'
})
export class Logger {
logs: string[] = []; // capture logs for testing
log(message: string) {
this.logs.push(message);
console.log('Logger==', message);
}
}
@Injectable({
providedIn: 'root'
})
export class EvenBetterLogger extends Logger {
constructor(private userService: UserService) { super(); }
override log(message: string) {
const name = this.userService.user.name;
super.log(`Message to ${name}: ${message}`);
}
}
也就是调用服务 Logger 的 log方法时,控制台会输出 Message to ****。
别名提供者:useExisting
useExisting 提供者键允许你将一个令牌映射到另一个。实际上,第一个令牌是与第二个令牌关联的服务的别名,创建了两种访问同一个服务对象的方式。
OldLoggerService
@Injectable({
providedIn: 'root'
})
export class OldLoggerService {
text = '';
constructor() { }
log() {
console.log("this old logger", this.text);
}
}
NewLoggerService
@Injectable({
providedIn: 'root',
})
export class NewLoggerService {
text = '';
constructor() { }
log() {
console.log("this new logger", this.text);
}
}
在Component中使用方法:
providers:[
{provide:OldLoggerService, useExisting:NewLoggerService}
]
使用这两个服务:
constructor(private oldLogger:OldLoggerService, private newLogger:NewLoggerService) {
this.newLogger.text = "newText";
this.oldLogger.log();
}
这时控制台输出 ‘this new logger"newText"’
useExisting和usrClass对比:
- useExisting:两个服务之间不需要是继承关系。但是需要有相同的属性和方法。
- usrClass:需要是继承关系
useFactory
useFactory 提供者键允许你通过调用工厂函数来创建依赖对象。使用这种方法,你可以根据 DI 和应用程序中其他地方的可用信息创建动态值。
比如创建的服务需要依赖一个boolean值,
这时候就需要在使用useFactory调用工厂函数来创建对象提供这个boolean值
@Injectable({
providedIn: 'root',
//如果服务中需要一些额外参数,例如boolean值,需要使用这种方式提供.
useFactory: (logger: Logger, userService: UserService) =>
new HeroService(logger, userService.user.isAuthorized),
//在服务中使用其他服务,需要这样添加依赖
deps: [Logger, UserService],
})
export class HeroService {
getListDatas() {
return ['张三', '李四'];
}
//初始化
constructor(
private logger: Logger,
private isAuthorized: boolean) { }
}
useValue
useValue 键允许你将固定值与某个 DI 令牌相关联。
根据代码理解,就是为组件初始化对象(令牌),提供默认参数:
interface AppConfig{
content:string
}
export const APP_CONFIG = new InjectionToken<AppConfig>('app.config');
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
viewProviders:[],
providers:[
{ provide: APP_CONFIG, useValue: { content: "全局的配置信息" } }
]
})
export class AppComponent {
constructor(@Inject(APP_CONFIG) private appConfig:AppConfig) {
console.log("this.appConfig.content==", this.appConfig.content);
}
ngOnInit() {
}
}