基于 angular/angular 源码深度解析
2026-03-06 | 技术深度解读
核心概念
Provider 系统
设计模式
实战应用
Angular 依赖注入系统是 Angular 框架的核心基础设施
核心价值:
源码位置:
angular/angular/packages/core/src/di/
Injector (abstract)
├── NullInjector (终止器)
└── R3Injector (运行时实现)
└── EnvironmentInjector (环境注入器)
InjectionToken (令牌)
Provider (提供者配置)
├── TypeProvider
├── ValueProvider
├── ClassProvider
├── FactoryProvider
└── ExistingProvider
export abstract class Injector {
static THROW_IF_NOT_FOUND = THROW_IF_NOT_FOUND;
static NULL: Injector = new NullInjector();
// 核心抽象方法
abstract get<T>(
token: ProviderToken<T>,
notFoundValue?: T,
options?: InjectOptions
): T;
// 静态工厂方法
static create(options: {
providers: Array<Provider | StaticProvider>;
parent?: Injector;
name?: string;
}): DestroyableInjector;
}
核心职责:根据 Token 查找并返回实例
abstract get<T>(
token: ProviderToken<T>, // 依赖令牌
notFoundValue?: T, // 未找到时的默认值
options?: InjectOptions // 注入选项
): T;
// InjectOptions 选项
interface InjectOptions {
optional?: boolean; // 可选依赖
self?: boolean; // 仅从当前注入器查找
skipSelf?: boolean; // 跳过当前注入器
}
static create(
options: {
providers: Array<Provider | StaticProvider>;
parent?: Injector; // 父注入器(层级结构)
name?: string; // 调试名称
}
): DestroyableInjector {
const name = options.name ?? '';
return createInjector(
{name},
options.parent,
options.providers,
name
);
}
返回:DestroyableInjector,可销毁的注入器实例
export class InjectionToken<T> {
readonly ngMetadataName = 'InjectionToken';
readonly ɵprov: unknown; // Tree-shakable provider
constructor(
protected _desc: string, // 描述(调试用)
options?: {
providedIn?: Type<any> | 'root' | 'platform' | 'any' | null;
factory: () => T; // 工厂函数
}
);
get multi(): InjectionToken<Array<T>>;
toString(): string;
}
constructor(
protected _desc: string,
options?: {
providedIn?: Type<any> | 'root' | 'platform' | 'any' | null;
factory: () => T;
}
) {
this.ɵprov = undefined;
if (typeof options == 'number') {
// 特殊标记(内部使用)
(this as any).__NG_ELEMENT_ID__ = options;
} else if (options !== undefined) {
// 创建 Tree-shakable provider
this.ɵprov = ɵɵdefineInjectable({
token: this,
providedIn: options.providedIn || 'root',
factory: options.factory,
});
}
}
Tree-shakable Token
// 创建带工厂的 InjectionToken
const API_URL = new InjectionToken<string>('api-url', {
providedIn: 'root',
factory: () => 'https://api.example.com'
});
// 使用时
constructor(@Inject(API_URL) private apiUrl: string) {}
优势:未使用时会被 tree-shake 移除
export class R3Injector extends EnvironmentInjector
implements PrimitivesInjector {
private records = new Map<ProviderToken<any>, Record<any> | null>();
private _ngOnDestroyHooks = new Set<OnDestroy>();
private _onDestroyHooks: Array<() => void> = [];
private _destroyed = false;
private injectorDefTypes: Set<Type<unknown>>;
constructor(
providers: Array<Provider | EnvironmentProviders>,
readonly parent: Injector,
readonly source: string | null,
readonly scopes: Set<InjectorScope>,
);
}
constructor(
providers: Array<Provider | EnvironmentProviders>,
readonly parent: Injector,
readonly source: string | null,
readonly scopes: Set<InjectorScope>,
) {
super();
// 处理所有 Provider
forEachSingleProvider(providers, (provider) =>
this.processProvider(provider)
);
// 注册自身
this.records.set(INJECTOR, makeRecord(undefined, this));
// 环境注入器
if (scopes.has('environment')) {
this.records.set(EnvironmentInjector, makeRecord(undefined, this));
}
}
override get<T>(
token: ProviderToken<T>,
notFoundValue: any = THROW_IF_NOT_FOUND,
options?: InjectOptions,
): T {
assertNotDestroyed(this);
// 特殊 token 处理
if (token.hasOwnProperty(NG_ENV_ID)) {
return (token as any)[NG_ENV_ID](this);
}
const flags = convertToBitFlags(options) as InternalInjectFlags;
// 设置注入上下文
const previousInjector = setCurrentInjector(this);
// ... 查找逻辑
}
// 检查 SkipSelf 标志
if (!(flags & InternalInjectFlags.SkipSelf)) {
// 在当前注入器中查找
let record = this.records.get(token);
if (record === undefined) {
// 尝试 Tree-shakable provider
const def = couldBeInjectableType(token) && getInjectableDef(token);
if (def && this.injectableDefInScope(def)) {
record = makeRecord(injectableDefOrInjectorDefFactory(token), NOT_YET);
} else {
record = null;
}
this.records.set(token, record);
}
if (record != null) {
return this.hydrate(token, record, flags);
}
}
private hydrate<T>(
token: ProviderToken<T>,
record: Record<T>,
flags: InternalInjectFlags
): T {
if (record.value === CIRCULAR) {
throw cyclicDependencyError(stringify(token));
} else if (record.value === NOT_YET) {
record.value = CIRCULAR; // 标记正在创建
// 调用工厂函数创建实例
record.value = record.factory!(undefined, flags);
}
// 注册生命周期钩子
if (hasOnDestroy(record.value)) {
this._ngOnDestroyHooks.add(record.value);
}
return record.value as T;
}
private processProvider(provider: SingleProvider): void {
provider = resolveForwardRef(provider);
let token = isTypeProvider(provider)
? provider
: resolveForwardRef(provider && provider.provide);
const record = providerToRecord(provider);
// Multi-provider 处理
if (!isTypeProvider(provider) && provider.multi === true) {
let multiRecord = this.records.get(token);
if (!multiRecord) {
multiRecord = makeRecord(undefined, NOT_YET, true);
multiRecord.factory = () => injectArgs(multiRecord!.multi!);
this.records.set(token, multiRecord);
}
multiRecord.multi!.push(provider);
} else {
this.records.set(token, record);
}
}
override destroy(): void {
assertNotDestroyed(this);
this._destroyed = true;
const prevConsumer = setActiveConsumer(null);
try {
// 调用所有 ngOnDestroy 钩子
for (const service of this._ngOnDestroyHooks) {
service.ngOnDestroy();
}
// 调用注册的销毁回调
for (const hook of this._onDestroyHooks) {
hook();
}
} finally {
// 清理引用
this.records.clear();
this._ngOnDestroyHooks.clear();
setActiveConsumer(prevConsumer);
}
}
职责:注入器树的叶子节点,标记查找结束
export class NullInjector implements Injector {
get(token: any, notFoundValue: any = THROW_IF_NOT_FOUND): any {
if (notFoundValue === THROW_IF_NOT_FOUND) {
const message = ngDevMode
? `No provider found for \`${stringify(token)}\`.`
: '';
const error = createRuntimeError(message, RuntimeErrorCode.PROVIDER_NOT_FOUND);
error.name = 'ɵNotFound';
throw error;
}
return notFoundValue;
}
}
行为:
使用场景:
// 创建独立注入器
const injector = Injector.create({
providers: [MyService]
});
// 无父注入器时,默认使用 NullInjector
injector.get(NotFoundService, null); // 返回 null
type Provider =
| TypeProvider // 直接提供类型
| ValueProvider // 提供静态值
| ClassProvider // 提供类实例
| ConstructorProvider // 构造函数提供者
| ExistingProvider // 别名提供者
| FactoryProvider // 工厂提供者
| any[]; // 嵌套数组
设计目标:灵活配置依赖的创建方式
interface ValueProvider {
provide: any; // 注入令牌
useValue: any; // 静态值
multi?: boolean; // 多值提供者
}
// 示例
const providers = [
{
provide: API_URL,
useValue: 'https://api.example.com'
}
];
适用场景:配置值、常量、外部对象
interface ClassProvider {
provide: any; // 注入令牌
useClass: Type<any>; // 类类型
multi?: boolean;
}
// 示例
const providers = [
{
provide: Logger,
useClass: ConsoleLogger
},
{
provide: StorageService,
useClass: LocalStorageService
}
];
适用场景:接口实现替换、类继承
interface FactoryProvider {
provide: any; // 注入令牌
useFactory: Function; // 工厂函数
deps?: any[]; // 依赖列表
multi?: boolean;
}
// 示例
const providers = [
{
provide: UserService,
useFactory: (api: ApiService, cache: CacheService) => {
return new UserService(api, cache);
},
deps: [ApiService, CacheService]
}
];
适用场景:动态创建、复杂依赖
interface ExistingProvider {
provide: any; // 注入令牌
useExisting: any; // 已有令牌
multi?: boolean;
}
// 示例
const providers = [
// 创建别名
{
provide: 'LoggerInterface',
useExisting: Logger
}
];
适用场景:别名、接口映射
type ProviderToken<T> =
| Type<T> // 类类型
| AbstractType<T> // 抽象类型
| InjectionToken<T>; // 注入令牌
// 使用示例
class MyService {}
const TOKEN = new InjectionToken<string>('token');
// 都可以作为 ProviderToken
injector.get(MyService);
injector.get(TOKEN);
export function createInjector(
defType: any, // 模块或组件类型
parent: Injector | null = null, // 父注入器
additionalProviders: Array<Provider> | null = null,
name?: string,
): Injector {
const injector = createInjectorWithoutInjectorInstances(
defType, parent, additionalProviders, name
);
// 解析初始化器
injector.resolveInjectorInitializers();
return injector;
}
function providerToRecord(provider: SingleProvider): Record<any> {
if (isValueProvider(provider)) {
// ValueProvider: 直接使用值
return makeRecord(undefined, provider.useValue);
} else {
// 其他类型: 创建工厂函数
const factory = providerToFactory(provider);
return makeRecord(factory, NOT_YET);
}
}
function makeRecord<T>(
factory: (() => T) | undefined,
value: T | {},
multi: boolean = false,
): Record<T> {
return {
factory: factory,
value: value,
multi: multi ? [] : undefined,
};
}
export function providerToFactory(provider: SingleProvider) {
if (isTypeProvider(provider)) {
// TypeProvider: 使用 Injectable 定义
return getFactoryDef(provider) ||
injectableDefOrInjectorDefFactory(provider);
} else if (isValueProvider(provider)) {
return () => resolveForwardRef(provider.useValue);
} else if (isFactoryProvider(provider)) {
return () => provider.useFactory(...injectArgs(provider.deps || []));
} else if (isExistingProvider(provider)) {
return (_, flags) => ɵɵinject(provider.useExisting, flags);
} else {
// ClassProvider
const classRef = resolveForwardRef(provider.useClass || provider.provide);
if (hasDeps(provider)) {
return () => new classRef(...injectArgs(provider.deps));
}
return getFactoryDef(classRef) || injectableDefOrInjectorDefFactory(classRef);
}
}
interface Record<T> {
factory: ((_: undefined, flags?: InternalInjectFlags) => T) | undefined;
value: T | {};
multi: any[] | undefined;
}
// Record 状态:
// - NOT_YET: 尚未创建实例
// - CIRCULAR: 正在创建(循环依赖检测)
// - 实际值: 已创建的实例
核心作用:缓存依赖实例和工厂函数
const NOT_YET = {};
const CIRCULAR = {};
private hydrate<T>(token, record, flags): T {
if (record.value === CIRCULAR) {
// 检测到循环依赖
throw cyclicDependencyError(stringify(token));
} else if (record.value === NOT_YET) {
// 标记为正在创建
record.value = CIRCULAR;
// 调用工厂(如果内部再次请求此 token,会触发 CIRCULAR 检测)
record.value = record.factory!(undefined, flags);
}
return record.value as T;
}
// 注入器层级结构
NullInjector (根)
└── PlatformInjector (平台级)
└── EnvironmentInjector (应用级)
├── ComponentInjector (组件级)
│ └── DirectiveInjector (指令级)
└── ComponentInjector (组件级)
└── ...
优势:组件隔离、作用域控制、懒加载支持
export abstract class EnvironmentInjector implements Injector {
abstract get<T>(
token: ProviderToken<T>,
notFoundValue?: T,
options?: InjectOptions
): T;
// 在注入器上下文中运行函数
abstract runInContext<ReturnT>(fn: () => ReturnT): ReturnT;
// 生命周期
abstract destroy(): void;
abstract get destroyed(): boolean;
abstract onDestroy(callback: () => void): () => void;
}
传统方式:
class UserService {
private api = new ApiService();
private cache = new CacheService();
}
依赖注入:
class UserService {
constructor(
private api: ApiService,
private cache: CacheService
) {}
}
优势:解耦、可测试、可配置
IoC (Inversion of Control)
// Angular 中的 IoC 容器
@Injectable({ providedIn: 'root' })
class MyService {
// 框架负责实例化和注入
}
// FactoryProvider 实现工厂模式
const providers = [
{
provide: DatabaseService,
useFactory: (config: ConfigService) => {
if (config.isProduction) {
return new ProductionDatabase(config.dbUrl);
} else {
return new MockDatabase();
}
},
deps: [ConfigService]
}
];
优势:运行时决策、条件创建
// Injector 本质上是一个服务定位器
class MyComponent {
constructor(private injector: Injector) {}
getService() {
// 手动查找服务(反模式!)
return this.injector.get(MyService);
}
}
// 推荐:使用构造函数注入
class MyComponent {
constructor(private service: MyService) {}
}
⚠️ 服务定位器模式应谨慎使用
1. 检查 SkipSelf 标志
↓ (未设置)
2. 在当前 injector.records 中查找
↓ (未找到)
3. 检查 Tree-shakable provider
↓ (不在作用域)
4. 请求父注入器
↓
5. 重复步骤 2-4 直到 NullInjector
↓ (仍未找到)
6. 返回 notFoundValue 或抛出错误
1. 找到 Record
↓
2. 检查 value 状态
- NOT_YET → 继续
- CIRCULAR → 抛出循环依赖错误
- 实际值 → 直接返回
↓
3. 设置 value = CIRCULAR
↓
4. 调用 factory() 创建实例
↓
5. 设置 value = 实例
↓
6. 注册 ngOnDestroy 钩子(如果有)
↓
7. 返回实例
// 定义多个 provider 到同一 token
const providers = [
{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true },
{ provide: HTTP_INTERCEPTORS, useClass: LoggingInterceptor, multi: true },
{ provide: HTTP_INTERCEPTORS, useClass: CacheInterceptor, multi: true }
];
// 注入时得到数组
constructor(@Inject(HTTP_INTERCEPTORS) interceptors: HttpInterceptor[]) {
// interceptors = [AuthInterceptor, LoggingInterceptor, CacheInterceptor]
}
应用场景:拦截器、守卫、插件系统
// 传统方式(不可 tree-shake)
@NgModule({
providers: [MyService] // 即使未使用也会打包
})
class AppModule {}
// Tree-shakable 方式
@Injectable({ providedIn: 'root' })
class MyService {}
// 或使用 InjectionToken
const TOKEN = new InjectionToken('token', {
providedIn: 'root',
factory: () => 'value'
});
优势:未使用的服务会被编译器移除
懒加载实例
// 实例仅在首次请求时创建
const record = makeRecord(factory, NOT_YET);
// hydrate 方法实现懒加载
if (record.value === NOT_YET) {
// 首次访问才创建
record.value = record.factory!(undefined, flags);
}
优化效果:减少启动时间、降低内存占用
// Record 缓存实例
interface Record<T> {
value: T | {}; // 缓存的实例
}
// 第二次访问直接返回缓存值
if (record.value !== NOT_YET && record.value !== CIRCULAR) {
return record.value; // 缓存命中
}
优化效果:避免重复创建、保证单例
// ❌ 不推荐:使用字符串
const API_URL = 'api-url';
providers: [{ provide: API_URL, useValue: '...' }]
// ✅ 推荐:使用 InjectionToken
const API_URL = new InjectionToken<string>('api-url');
// ✅ 推荐:带类型的 Token
interface AppConfig {
apiUrl: string;
timeout: number;
}
const APP_CONFIG = new InjectionToken<AppConfig>('app-config');
| 场景 | Provider 类型 |
|---|---|
| 类实例 | TypeProvider / ClassProvider |
| 配置值 | ValueProvider |
| 动态创建 | FactoryProvider |
| 别名 | ExistingProvider |
| 多个值 | multi: true |
// ❌ 循环依赖示例
@Injectable()
class ServiceA {
constructor(private serviceB: ServiceB) {}
}
@Injectable()
class ServiceB {
constructor(private serviceA: ServiceA) {}
}
// 运行时错误:Circular dependency detected
解决方案:重构代码、使用 forwardRef、提取共享服务
// ❌ 注入过多依赖
class MyComponent {
constructor(
private service1: Service1,
private service2: Service2,
private service3: Service3,
private service4: Service4,
private service5: Service5,
// ... 10+ 个依赖
) {}
}
// ✅ 重构:使用 facade 服务
class MyFacade {
constructor(private service1: Service1, private service2: Service2) {}
}
class MyComponent {
constructor(private facade: MyFacade) {}
}
| 特性 | Angular DI | React Context |
|---|---|---|
| 注入方式 | 构造函数 | useContext Hook |
| 类型安全 | ✅ 完整 | ⚠️ 需要手动 |
| 层级结构 | ✅ 内置 | ✅ Context 嵌套 |
| Provider 类型 | 5+ 种 | 单一 |
| 可选依赖 | ✅ @Optional() | ⚠️ 默认值 |
| 特性 | Angular DI | Vue provide/inject |
|---|---|---|
| 注入方式 | 构造函数 | inject() 函数 |
| 作用域 | 模块/组件级 | 组件树级 |
| 类型推断 | ✅ 完整 | ✅ TypeScript 支持 |
| 生命周期 | ✅ OnDestroy | ⚠️ 需手动管理 |
| 测试性 | ✅ 优秀 | ⚠️ 中等 |
官方文档
源码学习
推荐项目:Angular 官方示例、RxJS 集成示例
Angular 依赖注入系统核心要点
源码分析完成 ✨