您好,登录后才能下订单哦!
密码登录
登录注册
点击 登录注册 即表示同意《亿速云用户服务条款》
# Angular依赖注入怎么实现
## 目录
1. [依赖注入的核心概念](#依赖注入的核心概念)
2. [Angular DI系统架构](#angular-di系统架构)
3. [提供者的注册方式](#提供者的注册方式)
4. [注入器层级与查找机制](#注入器层级与查找机制)
5. [高级DI技术](#高级di技术)
6. [性能优化与陷阱](#性能优化与陷阱)
7. [实战案例解析](#实战案例解析)
---
## 依赖注入的核心概念
### 什么是依赖注入
依赖注入(Dependency Injection,DI)是一种设计模式,通过外部实体(通常是框架)将依赖对象传递给依赖方,而不是由依赖方自己创建。在Angular中,DI系统负责:
- 实例化服务
- 管理服务生命周期
- 解析依赖关系
### 设计优势
1. **解耦性**:组件无需知道如何创建依赖项
2. **可测试性**:可以轻松替换为mock对象
3. **可维护性**:依赖关系显式声明
4. **可重用性**:服务可在多个上下文中使用
### Angular中的典型依赖
```typescript
@Component({
selector: 'app-example',
template: `...`,
providers: [LoggerService] // 声明需要的服务
})
export class ExampleComponent {
constructor(private logger: LoggerService) {} // 注入服务
}
Injector(注入器)
get()
方法获取实例Provider(提供者)
Token(令牌)
Root Injector
│
├── Module Injector
│ └── LazyModule Injector
│
└── Element Injector
├── ComponentA Injector
└── ComponentB Injector
{ provide: LoggerService, useClass: LoggerService }
// 简写形式:
[LoggerService]
{ provide: API_URL, useValue: 'https://api.example.com' }
{
provide: AnalyticsService,
useFactory: (config: AppConfig) =>
config.production ? new ProdAnalytics() : new DevAnalytics(),
deps: [AppConfig]
}
{ provide: NewLogger, useExisting: OldLogger }
{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }
注册位置 | 作用域 | 典型用例 |
---|---|---|
@Injectable() | 根级(默认) | 全局单例服务 |
@NgModule() | 模块级 | 模块特定服务 |
@Component() | 组件级 | 组件私有服务 |
// 当在ChildComponent请求LoggerService时:
1. 检查ChildComponent注入器
2. 检查ParentComponent注入器
3. 检查AppModule注入器
4. 检查Root注入器
5. 抛出错误(如果未找到)
// 获取父组件实例
constructor(@SkipSelf() private parent: ParentComponent) {}
// 强制从当前注入器查找
constructor(@Host() private service: LocalService) {}
// 可选注入
constructor(@Optional() private maybeService?: SomeService) {}
@Component({
selector: 'app-dynamic',
template: `<ng-container #container></ng-container>`
})
export class DynamicComponent {
@ViewChild('container', { read: ViewContainerRef }) container: ViewContainerRef;
constructor(
private resolver: ComponentFactoryResolver,
private injector: Injector
) {}
createComponent() {
const factory = this.resolver.resolveComponentFactory(DynamicChildComponent);
this.container.createComponent(factory, 0, this.createChildInjector());
}
private createChildInjector(): Injector {
return Injector.create({
providers: [{ provide: DATA_TOKEN, useValue: { id: 123 } }],
parent: this.injector
});
}
}
// shared.module.ts
@NgModule({
providers: [SharedService]
})
export class SharedModule {}
// feature.module.ts
@NgModule({
imports: [SharedModule] // 共享服务
})
export class FeatureModule {}
// environment.ts
export const environment = {
production: false,
providers: [
{ provide: Logger, useClass: DevLogger }
]
};
// app.module.ts
@NgModule({
providers: [...environment.providers]
})
export class AppModule {}
@Injectable({ providedIn: 'root' })
@Injectable() export class B { constructor(a: A) {} // 循环依赖错误! }
2. **作用域混淆**
```typescript
@Injectable({ providedIn: 'root' })
export class CacheService {
// 全局状态可能被意外共享
}
@Component({
providers: [HeavyService] // 每次组件创建新实例
})
export class MyComponent {}
// logger.service.ts
@Injectable({ providedIn: 'root' })
export class LoggerService {
constructor(@Optional() @Inject(LOG_OPTIONS) private options) {}
log(message: string) {
if (this.options?.debug) {
console.log(`[DEBUG] ${message}`);
}
}
}
// app.module.ts
@NgModule({
providers: [
{ provide: LOG_OPTIONS, useValue: { debug: true } }
]
})
export class AppModule {}
// auth.interceptor.ts
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler) {
const authReq = req.clone({
headers: req.headers.set('Authorization', 'Bearer token')
});
return next.handle(authReq);
}
}
// logging.interceptor.ts
@Injectable()
export class LoggingInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler) {
console.log(`Request to ${req.url}`);
return next.handle(req);
}
}
// app.module.ts
@NgModule({
providers: [
{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true },
{ provide: HTTP_INTERCEPTORS, useClass: LoggingInterceptor, multi: true }
]
})
export class AppModule {}
// theme.service.ts
@Injectable({ providedIn: 'root' })
export class ThemeService {
private currentTheme = new BehaviorSubject<string>('light');
constructor(@Inject(DOCUMENT) private doc: Document) {}
setTheme(theme: string) {
this.currentTheme.next(theme);
this.doc.body.setAttribute('data-theme', theme);
}
}
// theme-picker.component.ts
@Component({
selector: 'app-theme-picker',
template: `
<button (click)="setTheme('light')">Light</button>
<button (click)="setTheme('dark')">Dark</button>
`
})
export class ThemePickerComponent {
constructor(private theme: ThemeService) {}
setTheme(theme: string) {
this.theme.setTheme(theme);
}
}
Angular的依赖注入系统是一个强大的设计,它: 1. 通过分层注入器实现灵活的作用域控制 2. 支持多种提供者注册模式 3. 提供高级功能如多提供者和可选注入 4. 与组件树和模块系统深度集成
掌握DI系统可以显著提升Angular应用的: - 架构清晰度 - 代码可维护性 - 测试便利性 - 运行时性能
建议开发者在实际项目中多实践不同的注入模式,深入理解各种装饰器(@Optional、@Host等)的行为差异,这将帮助构建更健壮的Angular应用。 “`
注:本文约2900字,涵盖了Angular依赖注入的核心机制、高级用法和实战案例。实际使用时可根据需要调整代码示例的详细程度或补充特定框架版本的注意事项。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。