Angular dependency injection
DI — внедрение зависимостей
Provider (Поставщик)
Инжекторы и провайдеры могу конфигурироваться на трех уровнях приложения, путём задания метаданных в декораторах:
- @Injectable() - на уровне сервиса.
- @NgModule() - на уровен модуля NgModule.
- @Component() - на уровне компонента.
providers: []
Определяется объектом ключ-значение и описывает как зависимость будет предоставлена.
Провайдер класса
providers: [{
provide: UserService, <== ключ (просто строка)
useClass: UserService <== класс
}]
Синтаксический «сахар»
providers: [UserService]
Провайдер переменной или константы
Зависмость от сущности, не являющейся классом. Вместо "прибитой" константы:
const sToken = 'Пирожок';
Используется
import { InjectionToken } from '@angular/core';
...
const sToken = new InjectionToken<string>('блюдо');
Тогда запись зависимости выглядит следующим образом:
providers: [{
provide: sToken, <== ключ
useValue: 'Пирожок' <== значение
}]
Провайдер «фабрика»
Используется для случая получения сущности по условию.
providers: [{
provide: UserService, <== ключ
useFactory: () => {
if (условие) {
return new UserServiceA();
} else {
return new UserServiceB();
}
}
}]
Множественные провайдеры
Для случая, когда вместо одной зависимости требуется массив используется multi: true
. При этом значение не перезаписывают массив, а добавляют в него значения.
...
providers: [
{ provide: sToken, useValue: 'Пирожок', multi: true },
{ provide: sToken, useValue: 'Печенька', multi: true }
]
...
export class AppComponent implements OnInit {
constructor(
@Inject(sToken) private _multiProvider,
) {}
ngOnInit() {
console.log(this._multiProvider); // выведет ["Пирожок", "Печенька"]
}
}
Injector
Механизм разрешающий зависимости и создающий сущности
Инжектор - объект в системе Angular, который может найти зависимость по ключу в своем кеше или создать зависимость с использованием настроенного провайдера (Provider). Инжекторы создаются для NgModules автоматически как часть процесса начальной загрузки и наследуются через иерархию компонентов.
Работа с инжектором вручную.
const injector = ReflectiveInjector.resolveAndCreate([UserService, { provide: sToken, useValue: 'Печенька'}]);
const cookie = injector.get(sToken);
const _uService = injector.get(UserService);
Dependency
Внедряемая зависимость
Обычно класс или константа. Тут всё просто - сущность, которую необходимо внедрить.
Зависимость Angular достаёт из декораторов @Component
, @Pipe
, @Directive
, @Inject
, @Injectable
.
Объявление зависимости
export class AppComponent implements OnInit {
constructor(private _uService: UserService) {} <== Зависимость от UserService
ngOnInit() {
this._uService.init();
}
}
@Inject
Наиболее известна запись зависимости:
constructor(private _uService: UserService) {}
Она эквивалентна:
constructor(@Inject(UserService) private _uService) {}
То есть имеется возможность вручную указать подставляемый ключ.
Этот декоратор используется когда создаётся InjectionToken
, потому что он не имеет специфичного тип (см. пример выше про блюдо, string
)