DI в Angular иерархичен: инжекторы образуют дерево, отражающее структуру компонентов/модулей. Когда компонент запрашивает зависимость, Angular поднимается вверх по дереву инжекторов до тех пор, пока не найдет провайдер — который определяет, получите ли вы одноэкземплярный синглтон или отдельный экземпляр для каждого компонента.
Иерархия инжектора
Root injector (app-wide) ← providedIn: 'root' lives here (one singleton)
└─ Module/Route injectors
└─ Component injector ← providers: [...] in @Component
└─ Child component injector
