关于saprfc:SAP-Spartacus-中的依赖注入-Dependency-Injection-介绍

47次阅读

共计 2393 个字符,预计需要花费 6 分钟才能阅读完成。

先理解 Angular 中的依赖注入

依赖项是指某个类执行其性能所需的服务或对象。依赖项注入(DI)是一种设计模式,在这种设计模式中,类会从内部源申请依赖项而不是让类 本人来 创立它们。
Angular 的 DI 框架会在实例化某个类时为其提供依赖。你能够应用 Angular DI 来进步应用程序的灵活性和模块化水平。

如何创立一个新的能够被注入的 service?

命令行:ng generate service heroes/hero

主动生成的代码,留神注解 @Injectable:

import {Injectable} from '@angular/core';

@Injectable({providedIn: 'root',})
export class HeroService {constructor() {}}

@Injectable() 装璜器会指定 Angular 能够在 DI 体系中应用此类。元数据 providedIn: ‘root’ 示意 HeroService 在整个应用程序中都是可见的。

配置提供者

通过配置提供者,你能够把服务提供给那些须要它们的利用部件。

依赖提供者会应用 DI 令牌来配置注入器,注入器会用它来提供这个依赖值的具体的、运行时版本。

如果你把服务类指定为提供者令牌,那么注入器的默认行为是用 new 来实例化那个类。

在上面这个例子中,Logger 类提供了 Logger 的实例。

providers: [Logger]

当应用提供者配置注入器时,会将该提供者与依赖项注入令牌(或叫 DI 令牌)关联起来。注入器容许 Angular 创立任何外部依赖项的映射。DI 令牌会充当该映射的键名。

当你应用 HeroService 类的类型来定义结构函数参数时,Angular 会注入与这个 HeroService 类令牌相关联的服务:

constructor(heroService: HeroService)

这里结构函数参数 heroService 实际上是一个令牌。

这个配置:

providers: [Logger]

实际上是上面写法的简写:

[{provide: Logger, useClass: Logger}]
  • provide 属性存有令牌,它作为一个 key,在定位依赖值和配置注入器时应用。
  • 第二个属性是一个提供者定义对象,它通知注入器要如何创立依赖值。提供者定义对象中的 key 能够是 useClass —— 就像这个例子中一样。也能够是 useExisting、useValue 或 useFactory。每一个 key 都用于提供一种不同类型的依赖。

不同的类能够提供雷同的服务。例如,以下代码通知注入器,当组件应用 Logger 令牌申请一个 logger 时,给它返回一个 BetterLogger.

这样,当咱们的应用程序,在 constructor 里应用上面代码试图注入 Logger 时:

constructor(logger: Logger)

运行时咱们拿到的就是 BetterLogger 实例。

injection token 的应用办法

  1. 应用 TypeScript interface 定义一个 AppConfig 类型(略)
  2. 基于 AppConfig 类型创立一个常量:
export const HERO_DI_CONFIG: AppConfig = {
  apiEndpoint: 'api.heroes.com',
  title: 'Dependency Injection'
};
  1. 要提供并注入配置对象,请在 @NgModule() 的 providers 数组中指定该对象。
providers: [{ provide: APP_CONFIG, useValue: HERO_DI_CONFIG}
],

下面代码里 provide 属性 APP_CONFIG 就是一个令牌,咱们还须要应用代码创立这个令牌。

import {InjectionToken} from '@angular/core';

export const APP_CONFIG = new InjectionToken<AppConfig>('app.config');

其中 AppConfig 通过类型参数传入令牌构造函数里。app.config 是令牌形容信息。

  1. 最初一步,在应用程序的构造函数里,用 @Inject,注入这个令牌。运行时,config 的值即为令牌关联的常量:HERO_DI_CONFIG
constructor(@Inject(APP_CONFIG) config: AppConfig) {this.title = config.title;}

为什么咱们不能间接把第一步用 interface 创立的 AppConfig 作为 provide 的值,而要大费周章,创立一个 InjectionToken 呢?

尽管 TypeScript 的 AppConfig 接口能够在类中提供类型反对,但它在依赖注入时却没有任何作用。在 TypeScript 中,接口是一项设计期工件,它没有可供 DI 框架应用的运行时示意模式或令牌。
当转译器把 TypeScript 转换成 JavaScript 时,接口就会隐没,因为 JavaScript 没有接口。
因为 Angular 在运行期没有接口,所以该接口不能作为令牌,也不能注入它。

因而下列代码不能工作:

// Can't use interface as provider token
[{provide: AppConfig, useValue: HERO_DI_CONFIG})]

看一个 SAP Spartacus 中 Injection Token 的应用例子:

export const PAGE_LAYOUT_HANDLER = new InjectionToken<PageLayoutHandler[]>('PageLayoutHandler');

在 Cart.module.ts 里应用到了这个令牌:

最初在 PageLayoutService 里应用到了这个令牌指向的服务实例:PageLayoutHandler 组成的数组。

更多 Jerry 的原创文章,尽在:” 汪子熙 ”:

正文完
 0