
Angular依赖注入注解inject()和注解@Inject
注解@Inject
Angular提供了注解@Inject来向组件或服务注入实例,例如:
@Injectable()
class AService{
constructor(@Inject(BService) bService:BService) {
}
}
这等同于添加访问修饰符后去掉注解,这也是我们常用的方式,上面示例可改为:
@Injectable()
class AService{
//去掉了注解@Inject,注意需要添加访问修饰符private/protec/public
constructor(private bService:BService) {
}
}
使用@Inject()注解有个限制,它只能在构造器参数上使用。
手动依赖注入方法inject()
inject()函数是Ivy引进来的,支持使用命令式做依赖注入。相对于注解@Inject仅限在构造函数参数上使用,inject()函数使用范围有所扩大,但仍有限制。inject()函数只能在以下几处使用:
- 由依赖注入实例化的类构造函数,例如@Injectable或@Component。
- 类字段属性的初始化
- 在为 Provider 或 @Injectable 的 useFactory 指定的工厂函数中。
- 在为InjectionToken 指定的工厂函数中。
这几处都是在类实例化创建的上下文中调用inject()函数。
类的构造函数
@Injectable()
class AService
private bService: BService;
constructor() {
this.bService = inject(BService);
}
}
类属性字段
@Injectable()
class AService
private bService: BService = inject(BService);
constructor() {
}
}
provider工厂函数
providers: [
{provide: AService, useFactory: () => {
const bService= inject(BService);
return new AService(bService);
}}
]
调用报NG0203错
在类创建上下文之外调用 inject() 函数会报错。有一个地方要注意,在创建类实例后,在类的其他方法(包括生命周期挂钩)中不允许调用 inject(), 如ngOnInit:
@Component({ ... })
export class MyComponent {
ngOnInit() {
// ERROR: 此处调用时已经晚了,因为MyComponent已经实例化完成
const myService= inject(MySerivce);
}
}
它报NG0203错误,信息类似:
core.mjs:6494 ERROR Error: NG0203: inject() must be called from an injection context
at injectInjectorOnly (core.mjs:4768:1)
at ɵɵinject (core.mjs:4778:1)
at Module.ɵɵdirectiveInject (core.mjs:14430:1)
angular版本的影响
在Angular13以及之前的版本,是不支持在@Component和@Directive中使用,Angular 14已修正以支持在组件和指令中使用,修复的信息:
fix(core): set correct context for inject() for component ctors (#45991)
The `inject()` function was introduced with Ivy to support imperative injection in factory/constructor contexts, such as directive or service constructors as well as factory functions defined in `@Injectable` or `InjectionToken`. However, `inject()` in a component/directive constructor did not work due to a flaw in the logic for creating the internal factory for components/directives. The original intention of this logic was to keep `ɵɵdirectiveInject` tree- shakable for applications which don't use any component-level DI. However, this breaks the `inject()` functionality for component/directive constructors. This commit fixes that issue and adds tests for all the various cases in which `inject()` should function. As a result `ɵɵdirectiveInject` is no longer tree-shakable, but that's totally acceptable as any application that uses `*ngIf` or `*ngFor` already contains this function. It's possible to change how `inject()` works to restore this tree-shakability if needed.