Dependency Injection Nang Cao trong Angular 2026: Providers, Tokens va Cau Hoi Phong Van
Tim hieu sau ve he thong dependency injection cua Angular bao gom chien luoc provider, InjectionToken, injector phan cap va cac cau hoi phong van thuong gap cho developer Angular co kinh nghiem.

He thong dependency injection cua Angular cung cap kha nang kiem soat chi tiet viec khoi tao service thong qua providers, tokens va injector phan cap. Thanh thao cac khai niem nay giup phan biet developer Angular co kinh nghiem voi nguoi moi trong phong van ky thuat va ma nguon san xuat.
Angular duy tri hai cay injector song song: cay ModuleInjector cho cac service duoc cung cap o cap module, va cay ElementInjector cho cac dependency co pham vi component. Qua trinh phan giai bat dau tu cap element va di len root.
Chien Luoc Cau Hinh Provider trong Angular DI
Angular cung cap nhieu chien luoc cau hinh provider, moi chien luoc phu hop voi cac truong hop su dung khac nhau. Cac cau hinh pho bien nhat su dung useClass, useValue, useFactory va useExisting.
import { ApplicationConfig, InjectionToken } from '@angular/core';
import { LoggerService } from './services/logger.service';
import { DebugLoggerService } from './services/debug-logger.service';
import { API_CONFIG, ApiConfig } from './config/api.config';
export const appConfig: ApplicationConfig = {
providers: [
// useClass: provide a different implementation
{ provide: LoggerService, useClass: DebugLoggerService },
// useValue: provide a static configuration object
{
provide: API_CONFIG,
useValue: { baseUrl: 'https://api.example.com', timeout: 5000 }
},
// useFactory: create dependency with runtime logic
{
provide: 'FEATURE_FLAGS',
useFactory: () => {
const env = import.meta.env.MODE;
return { debugMode: env === 'development', analytics: env === 'production' };
}
},
// useExisting: create an alias to another provider
{ provide: 'Logger', useExisting: LoggerService }
]
};Chien luoc useClass thay doi implementation ma khong can thay doi ma consumer. Chien luoc useValue cung cap cac doi tuong tinh nhu cau hinh. Chien luoc useFactory xu ly cac quyet dinh runtime, va useExisting tao alias cho truy cap da hinh.
InjectionToken cho Dependency Non-Class Type-Safe
Trong khi @Injectable hoat dong cho cac service dua tren class, cac gia tri non-class nhu doi tuong cau hinh, primitive hoac ham can InjectionToken. Token nay dong vai tro la khoa duy nhat trong registry DI cua Angular.
import { InjectionToken } from '@angular/core';
export interface ApiConfig {
baseUrl: string;
timeout: number;
retryAttempts: number;
}
// Generic parameter ensures type safety at injection point
export const API_CONFIG = new InjectionToken<ApiConfig>('api.config', {
providedIn: 'root',
factory: () => ({
baseUrl: 'https://api.sharpskill.dev',
timeout: 30000,
retryAttempts: 3
})
});
// Token for primitive values
export const MAX_UPLOAD_SIZE = new InjectionToken<number>('max.upload.size', {
providedIn: 'root',
factory: () => 10 * 1024 * 1024 // 10MB
});Tham so kieu generic tren InjectionToken<ApiConfig> lan truyen den loi goi inject(). TypeScript biet gia tri duoc inject khop voi kieu da khai bao, bat loi su dung sai tai thoi diem bien dich thay vi runtime.
Ham inject() so voi Constructor Injection
Angular 14 gioi thieu ham inject() nhu mot phuong phap thay the cho injection dua tren constructor. Trong Angular 20+, inject() da tro thanh cach tiep can duoc ua chuong, dac biet trong standalone component va cac ngu canh ham.
import { Injectable, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { API_CONFIG } from '../tokens/config.tokens';
@Injectable({ providedIn: 'root' })
export class UserService {
// Modern approach: inject() at field level
private readonly http = inject(HttpClient);
private readonly config = inject(API_CONFIG);
getUser(id: string) {
return this.http.get(`${this.config.baseUrl}/users/${id}`);
}
}
// Alternative: constructor injection (still valid)
@Injectable({ providedIn: 'root' })
export class UserServiceLegacy {
constructor(
private readonly http: HttpClient,
@Inject(API_CONFIG) private readonly config: ApiConfig
) {}
}Ham inject() loai bo boilerplate decorator cho token va cho phep dependency injection trong cac ngu canh non-class nhu functional guard, resolver va interceptor.
import { inject } from '@angular/core';
import { CanActivateFn, Router } from '@angular/router';
import { AuthService } from '../services/auth.service';
// Functional guard using inject()
export const authGuard: CanActivateFn = () => {
const authService = inject(AuthService);
const router = inject(Router);
if (authService.isAuthenticated()) {
return true;
}
return router.createUrlTree(['/login']);
};Ham inject() chi hoat dong trong injection context: trong qua trinh khoi tao class, trong factory function, hoac trong cac cau truc Angular ham. Goi no ben ngoai cac ngu canh nay se nem ra runtime error.
Sẵn sàng chinh phục phỏng vấn Angular?
Luyện tập với mô phỏng tương tác, flashcards và bài kiểm tra kỹ thuật.
Injector Phan Cap: ElementInjector vs EnvironmentInjector
Angular duy tri hai phan cap injector song song xac dinh pham vi va thu tu phan giai service. Hieu kien truc nay rat quan trong de kiem soat thoi gian song va kha nang hien thi cua service.
import { Injectable } from '@angular/core';
// Root-level singleton: single instance across entire app
@Injectable({ providedIn: 'root' })
export class GlobalDataService {
private data = new Map<string, unknown>();
set(key: string, value: unknown) { this.data.set(key, value); }
get(key: string) { return this.data.get(key); }
}
// Component-scoped: new instance per component
@Injectable()
export class ComponentDataService {
private data = new Map<string, unknown>();
set(key: string, value: unknown) { this.data.set(key, value); }
get(key: string) { return this.data.get(key); }
}import { Component } from '@angular/core';
import { ComponentDataService } from './services/component-data.service';
@Component({
selector: 'app-dashboard',
standalone: true,
// This component and all children get the same instance
providers: [ComponentDataService],
template: `
<app-widget />
<app-stats />
`
})
export class DashboardComponent {}Khi mot component khai bao provider, Angular tao mot instance moi co pham vi ElementInjector cua component do. Cac component con ke thua quyen truy cap vao provider cua parent tru khi chung khai bao provider rieng.
Thuat toan phan giai di theo duong dan nay:
- Kiem tra ElementInjector cua component yeu cau
- Di len cay ElementInjector den cac ancestor
- Kiem tra EnvironmentInjector (module hoac standalone provider)
- Di len root EnvironmentInjector
- Dat den NullInjector va nem loi neu
@Optional()khong duoc su dung
Modifier Phan Giai: @Self, @SkipSelf, @Optional, @Host
Cac modifier phan giai thay doi cach Angular tim kiem phan cap injector. Cac decorator nay hoat dong voi ca constructor injection va ham inject().
import { Component, Optional, SkipSelf, Self, inject } from '@angular/core';
import { PanelService } from './panel.service';
@Component({
selector: 'app-panel',
standalone: true,
providers: [PanelService],
template: `<ng-content />`
})
export class PanelComponent {
// @Self: only look in this component's injector, fail otherwise
private readonly localService = inject(PanelService, { self: true });
// @SkipSelf: skip this component, start search from parent
private readonly parentService = inject(PanelService, {
skipSelf: true,
optional: true
});
// @Optional: return null instead of throwing if not found
private readonly optionalService = inject(PanelService, { optional: true });
constructor() {
// localService is always the component's own instance
// parentService is the parent's instance or null
console.log('Local:', this.localService);
console.log('Parent:', this.parentService);
}
}Modifier @Host() gioi han phan giai vao injector cua host element va dung lai o ranh gioi component. Dieu nay huu ich khi directive can truy cap service duoc cung cap boi host component nhung khong nen vuon len cao hon trong cay.
import { Directive, inject, Host, Optional } from '@angular/core';
import { HighlightConfig } from './highlight.config';
@Directive({
selector: '[appHighlight]',
standalone: true
})
export class HighlightDirective {
// Only look at the host component's providers
private readonly config = inject(HighlightConfig, {
host: true,
optional: true
});
constructor() {
// config is null if host component didn't provide HighlightConfig
const color = this.config?.color ?? 'yellow';
// Apply highlighting...
}
}Multi-Provider cho He Thong Mo Rong
Multi-provider cho phep nhieu gia tri duoc dang ky duoi mot token duy nhat. Angular tra ve tat ca cac gia tri da dang ky duoi dang mang, cho phep kien truc plugin va cac mau mo rong.
import { InjectionToken } from '@angular/core';
export interface Validator {
validate(value: string): string | null;
}
export const VALIDATORS = new InjectionToken<Validator[]>('validators');import { ApplicationConfig } from '@angular/core';
import { VALIDATORS } from './validators.tokens';
const requiredValidator = {
validate: (value: string) => value ? null : 'Field is required'
};
const minLengthValidator = {
validate: (value: string) => value.length >= 3 ? null : 'Minimum 3 characters'
};
const emailValidator = {
validate: (value: string) =>
/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value) ? null : 'Invalid email format'
};
export const appConfig: ApplicationConfig = {
providers: [
{ provide: VALIDATORS, useValue: requiredValidator, multi: true },
{ provide: VALIDATORS, useValue: minLengthValidator, multi: true },
{ provide: VALIDATORS, useValue: emailValidator, multi: true }
]
};import { Injectable, inject } from '@angular/core';
import { VALIDATORS, Validator } from './validators.tokens';
@Injectable({ providedIn: 'root' })
export class ValidationService {
private readonly validators = inject(VALIDATORS);
validate(value: string): string[] {
// validators is an array of all registered validators
return this.validators
.map(v => v.validate(value))
.filter((error): error is string => error !== null);
}
}Co multi: true cho Angular biet phai thu thap tat ca cac provider cho token nay vao mot mang. Neu khong co no, cac provider sau se ghi de cac provider truoc.
Cau Hoi Phong Van ve Angular Dependency Injection
Phong van ky thuat thuong danh gia su hieu biet ve he thong DI cua Angular. Duoi day la cac cau hoi phan biet ung vien co kinh nghiem san xuat.
Q: Dieu gi xay ra khi cung cap cung mot service o ca cap module va component?
Provider cap component tao mot instance rieng biet co pham vi trong subtree cua component do. Service duoc inject trong subtree do nhan instance cua component, khong phai singleton cap module. Dieu nay cho phep co lap trang thai, vi du khi moi tab can trang thai form rieng.
Q: Tai sao su dung InjectionToken thay vi string literal?
String token co nguy co xung dot giua cac thu vien hoac cac phan khac nhau cua ung dung. InjectionToken tao mot tham chieu runtime duy nhat khong the xung dot. Tham so kieu generic cung cung cap an toan kieu tai thoi diem bien dich ma string token thieu.
Q: Khi nao inject() nem loi so voi tra ve undefined?
Mac dinh, inject() nem loi khi dependency khong tim thay. Truyen { optional: true } thay doi kieu tra ve thanh T | null va tra ve null thay vi nem loi. Dieu nay tuong ung voi hanh vi cua decorator @Optional().
Q: Giai thich su khac biet giua providedIn: 'root' va cung cap trong mang providers cua module.
Ca hai deu tao singleton, nhung providedIn: 'root' cho phep tree-shaking. Service chi duoc bao gom trong bundle neu thuc su duoc inject o dau do. Provider cap module luon duoc bao gom bat ke su dung.
Q: Lazy loading anh huong den pham vi service nhu the nao?
Lazy-loaded module nhan EnvironmentInjector con rieng cua chung. Service duoc cung cap trong lazy module co pham vi module do va cac con cua no. Service voi providedIn: 'root' van la singleton thuc su tren tat ca cac module, du lazy hay khong.
De luyen tap cac cau hoi ve Angular service va cac mau DI, xem cau hoi phong van Angular ve service va dependency injection.
Mau Thuc Te: Cau Hinh va Feature Flag
Cac ung dung thuc te ket hop cac khai niem DI nay de quan ly cau hinh. Mau nay su dung InjectionToken, factory provider va nhan thuc environment.
import { InjectionToken, inject, PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
export interface FeatureFlags {
newCheckout: boolean;
darkMode: boolean;
betaFeatures: boolean;
}
export const FEATURE_FLAGS = new InjectionToken<FeatureFlags>('feature.flags', {
providedIn: 'root',
factory: () => {
const platformId = inject(PLATFORM_ID);
if (!isPlatformBrowser(platformId)) {
// SSR: return safe defaults
return { newCheckout: false, darkMode: false, betaFeatures: false };
}
// Browser: check localStorage or remote config
const stored = localStorage.getItem('featureFlags');
if (stored) {
return JSON.parse(stored);
}
return { newCheckout: true, darkMode: false, betaFeatures: false };
}
});import { Directive, Input, TemplateRef, ViewContainerRef, inject } from '@angular/core';
import { FEATURE_FLAGS } from './feature-flags.config';
@Directive({
selector: '[appFeatureFlag]',
standalone: true
})
export class FeatureFlagDirective {
private readonly flags = inject(FEATURE_FLAGS);
private readonly templateRef = inject(TemplateRef<unknown>);
private readonly viewContainer = inject(ViewContainerRef);
@Input() set appFeatureFlag(flag: keyof typeof this.flags) {
if (this.flags[flag]) {
this.viewContainer.createEmbeddedView(this.templateRef);
} else {
this.viewContainer.clear();
}
}
}Directive nay render noi dung co dieu kien dua tren feature flag, voi cau hinh flag duoc tap trung trong mot injectable token duy nhat.
Bắt đầu luyện tập!
Kiểm tra kiến thức với mô phỏng phỏng vấn và bài kiểm tra kỹ thuật.
Thuc Hanh Angular DI San Xuat
- Su dung
providedIn: 'root'cho singleton toan ung dung duoc huong loi tu tree-shaking - Uu tien
inject()hon constructor injection trong Angular 20+ de co cu phap sach hon va tuong thich ham - Gioi han pham vi stateful service vao component khi can co lap, khong phai o cap module
- Tao
InjectionTokencho dependency non-class de dam bao an toan kieu va tranh xung dot - Ap dung
@Optional()khi dependency co the khong ton tai, dac biet cho plugin hoac tinh nang tuy chon - Test component voi overridden provider su dung
TestBed.overrideComponent()de co lap - Su dung multi-provider cho cac mau mo rong nhu validator, interceptor va handler
Bạn có tìm ra lỗi trong Angular không?
Một đoạn mã thật, một lỗi ẩn, mỗi ngày một lượt. Không cần tài khoản để thử.

Viết bởi
Anthony Fillion-MailletNgười sáng lập SharpSkill
Lập trình viên fullstack hơn 10 năm. Anh điều hành SharpSkill và chịu trách nhiệm về mọi nội dung đăng tại đây.
Cập nhật ngày 13 tháng 9, 2026
Thẻ
Chia sẻ
Bài viết liên quan

Cú Pháp Control Flow trong Angular 2026: @if, @for, @switch và Câu Hỏi Phỏng Vấn
Tìm hiểu cú pháp control flow Angular (@if, @for, @switch) thay thế các structural directive. Hướng dẫn đầy đủ với ví dụ code, tips migration và câu hỏi phỏng vấn kỹ thuật.

Angular Signals và Computed năm 2026: Reactivity Chi Tiết và Câu Hỏi Phỏng Vấn
Tìm hiểu Angular Signals và computed signals để có reactivity chi tiết trong Angular 20+. Hướng dẫn toàn diện bao gồm signal primitives, linkedSignal, tương tác RxJS và các câu hỏi phỏng vấn kỹ thuật.

Angular HttpClient và Interceptor năm 2026: Xử lý Request và Câu hỏi Phỏng vấn
Tìm hiểu cách sử dụng Angular HttpClient và functional interceptor để xử lý HTTP request, xác thực token, retry logic và caching. Bao gồm các câu hỏi phỏng vấn Angular thường gặp.