8.3 KiB
8.3 KiB
| name | description |
|---|---|
| repo-core-di | @repo/core 依赖注入框架使用指南。当需要创建注入器、注册提供者、使用装饰器(@Injectable, @Inject, @Optional等)、处理生命周期(OnInit, OnDestroy)、或解决循环依赖时使用此技能。适用于:(1) 创建和配置注入器层次结构 (2) 注册各类提供者(Value/Class/Factory/Lazy) (3) 使用参数装饰器控制注入行为 (4) 实现服务生命周期管理 (5) 使用 InjectionToken 和 ForwardRef |
@repo/core 依赖注入框架
核心概念
@repo/core 提供企业级依赖注入框架,支持层次化注入器、多种提供者类型、生命周期管理。
注入器层次结构
Root (根注入器)
└── Platform (平台注入器)
└── Application (应用注入器)
└── Feature (特性注入器)
快速开始
创建注入器
import { EnvironmentInjector, Injectable, InjectionToken } from '@repo/core'
// 定义类型安全的令牌
const API_URL = new InjectionToken<string>('API_URL')
// 创建根注入器
const rootInjector = EnvironmentInjector.createRootInjector([
{ provide: API_URL, useValue: 'https://api.example.com' }
])
// 创建应用注入器(继承根注入器)
const appInjector = EnvironmentInjector.createApplicationInjector([
UserService,
{ provide: LoggerService, useClass: LoggerService }
])
// 初始化(执行所有 @OnInit)
await appInjector.init()
// 获取服务
const userService = appInjector.get(UserService)
使用 @Injectable 装饰器
import { Injectable } from '@repo/core'
// providedIn: 'root' - 单例,自动注册到根注入器
@Injectable({ providedIn: 'root' })
class ConfigService {
apiUrl = 'https://api.example.com'
}
// providedIn: 'auto' - 不自动注册到根注入器,可在任何注入器中被按需解析
// 推荐用于请求级服务
@Injectable({ providedIn: 'auto' })
class RequestScopedService {
// 每次请求创建新实例
}
// 使用工厂函数
@Injectable({
providedIn: 'root',
useFactory: (config: ConfigService) => new ApiClient(config.apiUrl),
deps: [ConfigService]
})
class ApiClient {
constructor(public baseUrl: string) {}
}
提供者类型
值提供者 (ValueProvider)
const API_URL = new InjectionToken<string>('API_URL')
const CONFIG_TOKEN = new InjectionToken<AppConfig>('CONFIG_TOKEN')
{ provide: API_URL, useValue: 'https://api.example.com' }
{ provide: CONFIG_TOKEN, useValue: { debug: true, timeout: 5000 } }
类提供者 (ClassProvider)
{ provide: UserService, useClass: UserService }
{ provide: Logger, useClass: ConsoleLogger } // 接口映射到实现
工厂提供者 (FactoryProvider)
{
provide: DatabaseConnection,
useFactory: (config: ConfigService) => {
return new DatabaseConnection(config.dbUrl)
},
deps: [ConfigService]
}
别名提供者 (ExistingProvider)
const LOGGER_TOKEN = new InjectionToken<Logger>('Logger')
{ provide: LOGGER_TOKEN, useExisting: LoggerService }
延迟提供者 (LazyProvider)
const LAZY_CONFIG = new InjectionToken<AppConfig>('LAZY_CONFIG')
// 延迟类 - 首次访问时才实例化
{ provide: HeavyService, useLazyClass: HeavyService }
// 延迟工厂
{ provide: LAZY_CONFIG, useLazyFactory: () => loadConfig(), deps: [] }
多值提供者 (Multi Provider)
{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }
{ provide: HTTP_INTERCEPTORS, useClass: LoggingInterceptor, multi: true }
// 获取时返回数组
const interceptors = injector.get(HTTP_INTERCEPTORS) // [AuthInterceptor, LoggingInterceptor]
参数装饰器
@Inject - 显式指定注入令牌
const API_URL = new InjectionToken<string>('API_URL')
class UserController {
constructor(
@Inject(UserService) private userService: UserService,
@Inject(API_URL) private apiUrl: string
) {}
}
@Optional - 可选注入
class NotificationService {
constructor(
@Optional(EmailService) private email?: EmailService // 不存在时为 null
) {}
}
@Self - 仅在当前注入器查找
class ChildComponent {
constructor(
@Self(LocalService) private local: LocalService // 不查找父注入器
) {}
}
@SkipSelf - 跳过当前注入器
class ChildService {
constructor(
@SkipSelf(ParentService) private parent: ParentService // 从父注入器开始查找
) {}
}
@Host - 在宿主注入器查找
class DirectiveService {
constructor(
@Host(HostService) private host: HostService
) {}
}
生命周期管理
@OnInit 装饰器
import { Injectable, OnInit } from '@repo/core'
@Injectable({ providedIn: 'root' })
class DatabaseService implements OnInit {
private connection: Connection
@OnInit()
async onInit() {
this.connection = await this.connect()
console.log('Database connected')
}
private async connect() {
// 连接逻辑
}
}
OnDestroy 接口
import { Injectable, OnDestroy } from '@repo/core'
@Injectable({ providedIn: 'root' })
class CacheService implements OnDestroy {
async onDestroy() {
await this.flush()
console.log('Cache flushed')
}
}
// 销毁注入器时自动调用
await injector.destroy()
APP_INITIALIZER - 应用初始化器
import { APP_INITIALIZER, InjectionToken } from '@repo/core'
const appInjector = EnvironmentInjector.createApplicationInjector([
{
provide: APP_INITIALIZER,
useValue: {
provide: new InjectionToken('DB_INIT'),
deps: [ConfigService],
init: async () => {
await initDatabase()
}
},
multi: true
},
{
provide: APP_INITIALIZER,
useValue: {
provide: new InjectionToken('CACHE_INIT'),
deps: [new InjectionToken('DB_INIT')], // 依赖 DB_INIT
init: async () => {
await initCache()
}
},
multi: true
}
])
// 按依赖顺序执行初始化器
await appInjector.init()
InjectionToken
import { InjectionToken } from '@repo/core'
// 创建类型安全的令牌
const API_URL = new InjectionToken<string>('API_URL')
const CONFIG = new InjectionToken<AppConfig>('CONFIG')
const LOGGER_LEVEL = new InjectionToken<LoggerLevel>('LOGGER_LEVEL')
// 注册
const injector = EnvironmentInjector.createRootInjector([
{ provide: API_URL, useValue: 'https://api.example.com' },
{ provide: CONFIG, useValue: { debug: true } }
])
// 获取(类型安全)
const url: string = injector.get(API_URL)
const config: AppConfig = injector.get(CONFIG)
ForwardRef - 解决循环依赖
import { Injectable, Inject, forwardRef } from '@repo/core'
@Injectable({ providedIn: 'root' })
class ServiceA {
constructor(
@Inject(forwardRef(() => ServiceB)) private serviceB: ServiceB
) {}
}
@Injectable({ providedIn: 'root' })
class ServiceB {
constructor(
@Inject(forwardRef(() => ServiceA)) private serviceA: ServiceA
) {}
}
便捷工厂函数
import {
createRootInjector,
createPlatformInjector,
createApplicationInjector,
createFeatureInjector
} from '@repo/core'
// 简化创建
const root = createRootInjector([...providers])
const platform = createPlatformInjector([...providers])
const app = createApplicationInjector([...providers])
const feature = createFeatureInjector([...providers], parentInjector)
最佳实践
- 使用 providedIn: 'root' - 大多数服务应该是单例
- 避免循环依赖 - 使用 ForwardRef 仅作为最后手段
- 使用 InjectionToken - 为非类类型创建类型安全令牌
- 实现 OnDestroy - 清理资源(连接、订阅等)
- 使用 APP_INITIALIZER - 管理复杂的初始化顺序
- 延迟加载 - 对重型服务使用 useLazyClass/useLazyFactory
参考文档
- 详细 API 参考:见 references/api.md
- 提供者类型详解:见 references/providers.md
- 请求级注入器:见 references/request-scoped-injector.md - HTTP 请求隔离、CURRENT_USER 注入、Controller 生命周期
- 错误处理系统:见 references/errors.md - 预定义错误类、ErrorFactory、ErrorSerializer