Angular中如何将非单例服务注入另一个非单例服务?
Great question—let’s break this down clearly, since Angular’s DI system is all about keeping your code decoupled and maintainable.
1. Where should you declare ServiceB?
The best practice is to let ServiceA manage its own dependencies, not force ComponentA to handle them. You have two clean options:
Option 1: Use providedIn in ServiceB's @Injectable decorator
This is the modern, recommended approach. Declare ServiceB with providedIn: 'root' (or a specific module if you need scoped access):
// service-b.ts import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root' // Makes ServiceB an app-wide singleton }) export class ServiceB { // ... your service logic }
With this setup, ServiceA can simply inject ServiceB in its constructor, and ComponentA never needs to know ServiceB exists at all. Perfect for decoupling!
Option 2: Add ServiceB to your module's providers array
If you need to restrict ServiceB to a specific module (e.g., only components in FeatureModule should use it), add it to that module's providers:
// feature.module.ts import { NgModule } from '@angular/core'; import { ServiceB } from './service-b'; @NgModule({ providers: [ServiceB] // Scoped to this module and its components }) export class FeatureModule { }
Again, ServiceA can inject ServiceB directly—ComponentA still doesn't need to reference ServiceB.
2. Does declaring ServiceB in a module make it a singleton?
It depends on the module type:
- Root module (AppModule): Yes, adding ServiceB to AppModule's providers will create a single instance shared across the entire app.
- Feature module (especially lazy-loaded ones): No. If you add ServiceB to a lazy-loaded module's providers, Angular creates a new instance of ServiceB for that module's injector. This means you'll have multiple instances if the module is loaded multiple times or if multiple modules declare ServiceB in their providers.
Pro tip: Using providedIn: 'root' guarantees a true app-wide singleton, even for lazy-loaded modules, which is why it's the default recommendation.
3. Why is adding ServiceB to ComponentA's providers a bad idea?
You’re right—it works, but it’s not ideal for two big reasons:
- Tight coupling: ComponentA now has to know about ServiceA's internal dependencies, which breaks encapsulation. ServiceA should be responsible for its own dependencies, not the components that use it. If ServiceA ever adds or removes a dependency later, you’ll have to update ComponentA too—extra maintenance work!
- Instance duplication: Adding ServiceB to ComponentA's providers means every instance of ComponentA (and all its child components) will get a new, separate instance of ServiceB. Unless you explicitly want multiple isolated instances of ServiceB (which is rare), this is wasteful and can lead to unexpected behavior if you intended a singleton.
Quick Recap of Best Practices
- ✅ Do use
@Injectable({ providedIn: 'root' })for ServiceB (app-wide singleton, clean decoupling) - ✅ Do add ServiceB to a module's providers if you need scoped access
- ❌ Don’t add ServiceB to ComponentA's providers unless you specifically need component-scoped instances and accept the coupling
内容的提问来源于stack exchange,提问作者David

