🅰️ Angular 依赖注入深度解析

Dependency Injection System Deep Dive

基于 angular/angular 源码深度解析
2026-03-06 | 技术深度解读

📑 目录

核心概念

  • Injector 基类
  • InjectionToken
  • R3Injector 运行时
  • NullInjector

Provider 系统

  • ValueProvider
  • ClassProvider
  • FactoryProvider
  • ExistingProvider

设计模式

  • 依赖注入模式
  • 控制反转
  • 工厂模式
  • 服务定位器

实战应用

  • 最佳实践
  • 反模式
  • 性能优化
  • 框架对比

🎯 项目简介

Angular 依赖注入系统是 Angular 框架的核心基础设施

核心价值:

  • 解耦组件与依赖实现
  • 提供层级化的依赖管理
  • 支持多种 Provider 类型
  • Tree-shakable 优化

源码位置:

angular/angular/packages/core/src/di/

🏗️ 核心架构

Injector (abstract)
    ├── NullInjector (终止器)
    └── R3Injector (运行时实现)
            └── EnvironmentInjector (环境注入器)

InjectionToken (令牌)
Provider (提供者配置)
    ├── TypeProvider
    ├── ValueProvider
    ├── ClassProvider
    ├── FactoryProvider
    └── ExistingProvider

📦 Injector 基类

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;
}

🔍 Injector.get 方法

核心职责:根据 Token 查找并返回实例

abstract get<T>(
  token: ProviderToken<T>,     // 依赖令牌
  notFoundValue?: T,            // 未找到时的默认值
  options?: InjectOptions       // 注入选项
): T;

// InjectOptions 选项
interface InjectOptions {
  optional?: boolean;    // 可选依赖
  self?: boolean;        // 仅从当前注入器查找
  skipSelf?: boolean;    // 跳过当前注入器
}

⚙️ Injector.create 静态方法

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,可销毁的注入器实例

🏷️ InjectionToken 类

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;
}

🔨 InjectionToken 构造函数

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,
    });
  }
}

🏭 InjectionToken 工厂模式

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 移除

🔧 R3Injector 核心类

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>,
  );
}

🏗️ R3Injector 构造函数

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));
  }
}

🎯 R3Injector.get 核心方法

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);
  // ... 查找逻辑
}

🔍 R3Injector 查找逻辑

// 检查 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);
  }
}

💧 R3Injector.hydrate 实例化

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;
}

⚙️ R3Injector.processProvider

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);
  }
}

💥 R3Injector.destroy 生命周期

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);
  }
}

🚫 NullInjector 终止器

职责:注入器树的叶子节点,标记查找结束

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;
  }
}

🎯 NullInjector.get 方法

行为:

  • 未提供 notFoundValue → 抛出错误
  • 提供了 notFoundValue → 返回该值

使用场景:

// 创建独立注入器
const injector = Injector.create({
  providers: [MyService]
});

// 无父注入器时,默认使用 NullInjector
injector.get(NotFoundService, null); // 返回 null

📋 Provider 类型系统

type Provider =
  | TypeProvider          // 直接提供类型
  | ValueProvider         // 提供静态值
  | ClassProvider         // 提供类实例
  | ConstructorProvider   // 构造函数提供者
  | ExistingProvider      // 别名提供者
  | FactoryProvider       // 工厂提供者
  | any[];                // 嵌套数组

设计目标:灵活配置依赖的创建方式

📦 ValueProvider

interface ValueProvider {
  provide: any;          // 注入令牌
  useValue: any;         // 静态值
  multi?: boolean;       // 多值提供者
}

// 示例
const providers = [
  {
    provide: API_URL,
    useValue: 'https://api.example.com'
  }
];

适用场景:配置值、常量、外部对象

🏫 ClassProvider

interface ClassProvider {
  provide: any;          // 注入令牌
  useClass: Type<any>;   // 类类型
  multi?: boolean;
}

// 示例
const providers = [
  {
    provide: Logger,
    useClass: ConsoleLogger
  },
  {
    provide: StorageService,
    useClass: LocalStorageService
  }
];

适用场景:接口实现替换、类继承

🏭 FactoryProvider

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]
  }
];

适用场景:动态创建、复杂依赖

🔗 ExistingProvider

interface ExistingProvider {
  provide: any;          // 注入令牌
  useExisting: any;      // 已有令牌
  multi?: boolean;
}

// 示例
const providers = [
  // 创建别名
  {
    provide: 'LoggerInterface',
    useExisting: Logger
  }
];

适用场景:别名、接口映射

🏷️ ProviderToken 类型

type ProviderToken<T> = 
  | Type<T>              // 类类型
  | AbstractType<T>      // 抽象类型
  | InjectionToken<T>;   // 注入令牌

// 使用示例
class MyService {}

const TOKEN = new InjectionToken<string>('token');

// 都可以作为 ProviderToken
injector.get(MyService);
injector.get(TOKEN);

🔧 createInjector 工厂函数

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;
}

🔄 providerToRecord 转换

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,
  };
}

🏭 providerToFactory 转换

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);
  }
}

📝 Record 接口

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 (组件级)
                            └── ...

优势:组件隔离、作用域控制、懒加载支持

🌐 EnvironmentInjector

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)

  • 传统:对象自己创建依赖
  • IoC:外部容器提供依赖
// 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. 返回实例

📦 Multi Provider 机制

// 定义多个 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 Shakable Providers

// 传统方式(不可 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;  // 缓存命中
}

优化效果:避免重复创建、保证单例

✅ 最佳实践:Token 设计

// ❌ 不推荐:使用字符串
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 选择

场景 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) {}
}

⚔️ 与 React DI 对比

特性 Angular DI React Context
注入方式 构造函数 useContext Hook
类型安全 ✅ 完整 ⚠️ 需要手动
层级结构 ✅ 内置 ✅ Context 嵌套
Provider 类型 5+ 种 单一
可选依赖 ✅ @Optional() ⚠️ 默认值

⚔️ 与 Vue DI 对比

特性 Angular DI Vue provide/inject
注入方式 构造函数 inject() 函数
作用域 模块/组件级 组件树级
类型推断 ✅ 完整 ✅ TypeScript 支持
生命周期 ✅ OnDestroy ⚠️ 需手动管理
测试性 ✅ 优秀 ⚠️ 中等

📚 扩展阅读

官方文档

  • Angular DI 官方指南
  • Provider 配置详解
  • 层级注入器

源码学习

  • packages/core/src/di/
  • R3Injector 实现
  • Tree-shakable 机制

推荐项目:Angular 官方示例、RxJS 集成示例

🎯 总结

Angular 依赖注入系统核心要点

  • Injector:依赖查找和实例化的核心
  • Provider:灵活的依赖配置方式
  • InjectionToken:类型安全的令牌系统
  • 层级结构:组件隔离和作用域控制
  • Tree-shakable:优化打包体积

源码分析完成 ✨