深入理解Angular中的依赖注入(2)

除了组件依赖服务,服务间依的相互调用也很寒常见。例如我们想给我们的汉堡机器人加上一个计数器,来记录它的生产状况,但是计数器又依靠电源来工作,我们就可以用一个服务来实现:

// power.service.ts import { Injectable } from '@angular/core'; @Injectable() export class PowerService { // power come from here.. } // count.service.ts import { Injectable } from '@angular/core'; import { PowerService } from './power/power.service'; @Injectable() export class CountService { constructor(private power: PoowerService) {} } // app.component.ts 这里是当前组件,其实模块中的注入也一样,后面讲到 //... providers: [ CountService, PowerService ]

这里需要注意的是@Injectable装饰器是非必须的,因为只有一个服务依赖其他服务的时候才必须需要使用@Injectable显式装饰,来表示这个服务需要依赖,所以我们的PowerService并不是必须加上@Injectable装饰器的,可是,Angular官方推荐是否依赖其他服务,都应该使用@Injectable来装饰服务。

3. 在模块中注入服务

在模块中注册服务和在组件中注册服务的方法是一样的,只是在模块中注入的服务在整个组件中都是可用的。

// app.module.ts import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppComponent } from './app.component'; @NgModule({ declarations: [ AppComponent, ], imports: [ BrowserModule ], providers: [CountService, PowerService], bootstrap: [AppComponent] }) export class AppModule { }

与在组件中注入不同的是,在Angular应用启动的时候,它好首先加载这个模块需要的所有依赖,,此时会生成一个全局的根注入器,由该依赖创建的依赖注入对象会再整个应用中可见,并共享一个实例。

Angular没有模块级作用域这个概念,只有应用程序级作用域和组件级作用域,这种设计主要是考虑模块的扩展性,一个应用通常由多个模块合并和成,在@NgModule中注册的服务,默认在整个应用中可用。

下面说两种特殊情况:

假设在两个模块中使用同样的Token注入了同一个服务,并且这两个模块先后导入到了根组件中:

// ... @NgModule({ imports: [ AModule, BModule ] // ... })

那么后面导入的模块中的服务会覆盖前面导入模块中的服务,也就是说BModule中的服务会覆盖AModule中的服务,即使是在AModule中注入的服务,同样使用的是BMoudle中提供的实例。

还是假设两个模块同样使用同一个Token注入了同一个服务,但是BModule模块是导入在AModule模块中的:

// a.module.ts // ... @NgModule({ imports: [BModule] })

那么这种情况下两个模块使用的都是AModule中注入的服务。可以推断出在根模块中注入的服务是拥有最高优先级的,你可以在任何地方放心使用。

三、Provider

1. Provider的理解

Provider是有必要单独提出来一节的,上面第二节中我们其实只是简单的使用了其中一种的provider下面来详细说一下Provider

在Angular中,Provider描述了注入器(Injector)如何初始化令牌(Token)所对应的依赖服务。Provider一个运行时的依赖,注入器依靠它来创建服务对象的实例。

比如我们上面用到的例子:

// ... @Component({ //... // 2. 在组件中配置注入器 providers: [ MyService ] //... })

实际上它的完整形式应该是这样的:

@Component({ //... // 2. 在组件中配置注入器 providers: [ {provide: MyService, useClass: MyService} ] //... })

所以说我们上面只使用了一种provider: 类Provider(ClassProvider)。

2. Provider注册方式

上面提到我只使用了其中一种注册方式,那么下面介绍Angular中提供的四中常见的注册方式:

类Provider(ClassProvider)

值Provider(ValueProvider)

别名Provider(ExistingProvider)

工厂Provider(FactoryProvider)

1. 类Provider

类Provider 基于令牌(Token)指定依赖项,这种方式可是让依赖被动态指定为其他不同的具体实现,只要接口不变,对于使用方就是透明的。比如数据渲染服务(Render),Render服务对上层提供的接口是固定的,倒是底层的渲染方式可以不同:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wyfxgd.html