Angular:provide 中useClass useValue useExisting useFactory 区别和用法

91 阅读1分钟

非常棒的问题 Amanda!💡

在 Angular 的依赖注入(DI)系统中,useClass, useValue, useExisting, useFactory 是用来告诉 Angular:

“当某个东西要被注入时,我希望你如何创建或获取它的实例。”


🔍 四种方式对比(+ 示例)

方式用途是否支持依赖注入创建方式
useClass用某个类创建新实例(最常见)✅ 是new MyClass(...)
useValue用现成的对象/值❌ 否直接使用这个值
useExisting复用已有的实例(别名)✅ 是指向已有提供者
useFactory用函数返回实例(可以自定义复杂逻辑)✅ 是调用函数并注入依赖

✅ 全部例子:以 LoggerService 为核心来说明

🔧 准备一个服务类

export class LoggerService {
  log(msg: string) {
    console.log('LoggerService: ' + msg);
  }
}

1️⃣ useClass: 最常见,默认行为

providers: [
  { provide: LoggerService, useClass: LoggerService }
]

➡️ 相当于:每次注入 LoggerService,都用这个类构造一个新实例。


2️⃣ useValue: 使用已有的对象或值

export const simpleLogger = {
  log: (msg: string) => console.log('SimpleLogger: ' + msg)
};

providers: [
  { provide: LoggerService, useValue: simpleLogger }
]

➡️ LoggerService 实际上就是这个 JS 对象,不是类实例。

🧠 适合 mock 数据、常量、配置对象。


3️⃣ useExisting: 指向另一个已提供的 token

export class BetterLoggerService {
  log(msg: string) {
    console.log('BetterLogger: ' + msg);
  }
}

providers: [
  BetterLoggerService,
  { provide: LoggerService, useExisting: BetterLoggerService }
]

➡️ LoggerServiceBetterLoggerService 实际上是同一个实例

🧠 用于别名、兼容旧代码。


4️⃣ useFactory: 工厂函数创建,适合带逻辑、参数的情况

export function loggerFactory(): LoggerService {
  const logger = new LoggerService();
  logger.log('Logger created by factory!');
  return logger;
}

providers: [
  { provide: LoggerService, useFactory: loggerFactory }
]

➡️ 每次注入 LoggerService,调用 loggerFactory() 返回实例。


➕ 示例:带依赖的 useFactory

export function advancedLoggerFactory(http: HttpClient): LoggerService {
  const logger = new LoggerService();
  logger.log('Logger created with HTTP capability');
  return logger;
}

providers: [
  {
    provide: LoggerService,
    useFactory: advancedLoggerFactory,
    deps: [HttpClient]
  }
]

🧠 总结口诀

场景用法
类创建实例(最常见)useClass
已有对象、常量、MockuseValue
想让多个 Token 共享实例useExisting
要带逻辑、传参、复杂创建过程useFactory