L'injection de dépendances d'Angular est hiérarchique : les injecteurs forment un arbre qui reflète l'arborescence des composants/modules. Quand un composant demande une dépendance, Angular remonte vers le haut l'arbre des injecteurs jusqu'à trouver un provider — qui contrôle si vous obtenez un singleton partagé ou une instance distincte par composant.
Pourquoi c'est important
Root injector (app-wide) ← providedIn: 'root' lives here (one singleton)
└─ Module/Route injectors
└─ Component injector ← providers: [...] in @Component
└─ Child component injector
Une recherche commence au composant demandeur et remonte jusqu'à la racine. Le premier provider trouvé l'emporte.
L'endroit où vous fournissez détermine la portée
// 1. App-wide singleton — ONE instance shared everywhere
@Injectable({ providedIn: "root" })
export class AuthService {}
// 2. Component-scoped — a NEW instance per component (and its children)
@Component({
selector: "app-widget",
providers: [DataService], // each <app-widget> gets its OWN DataService
})
export class WidgetComponent {}
C'est le levier clé : providedIn: 'root' donne une seule instance partagée ; lister un provider dans le tableau providers d'un composant crée une nouvelle instance limitée à ce sous-arbre de composant (utile pour isoler l'état par composant).
Modificateurs d'injection
constructor(
@Optional() private logger: Logger, // null instead of error if not provided
@Self() private local: LocalService, // only look in THIS injector
@SkipSelf() private parent: ParentService, // skip self, start at the parent
@Host() private host: HostService, // stop at the host component
) {}
Ces décorateurs contrôlent jusqu'où Angular cherche dans l'arbre des injecteurs — par exemple @Optional évite une erreur quand une dépendance est manquante, @SkipSelf force l'utilisation de l'instance d'un parent.
Tokens d'injection pour les dépendances non-class
export const API_URL = new InjectionToken<string>("apiUrl");
// provide: { provide: API_URL, useValue: "https://api.example.com" }
constructor(@Inject(API_URL) private apiUrl: string) {}
Les tokens vous permettent d'injecter des valeurs/configurations (pas seulement des classes) et d'échanger les implémentations (useClass, useValue, useFactory).
Pourquoi c'est important
Comprendre l'injecteur hiérarchique explique pourquoi un service est partagé au niveau de l'application par rapport à être dupliqué par composant — une source fréquente de confusion « pourquoi ces composants partagent/ne partagent-ils pas l'état ? ».
Contrôler la portée du provider (root vs providers du composant), utiliser des modificateurs (@Optional, @SkipSelf), et les tokens d'injection pour la configuration/les implémentations interchangeables est ce qui rend l'injection de dépendances d'Angular puissante pour l'architecture et les tests.
