Angular 6:如何通过providedIn自定义@Injectable()依赖注入提供者?
能否通过
providedIn实现Angular 5中的抽象类与实现类注入配置? 很遗憾,你尝试的写法是行不通的——@Injectable()装饰器的配置对象里并没有provide这个属性,Angular不会识别这个配置,反而会直接抛出错误。
要在Angular 6+中实现和Angular 5完全相同的效果(即注入抽象类时自动获取其实现类的实例),这里有两种推荐的方案:
方案1:保留NgModule配置+结合providedIn优化包体积
你可以继续沿用Angular 5的providers数组配置方式,同时给实现类加上providedIn: 'root'来享受Angular的摇树优化(Tree Shaking),减小最终包体积:
// 定义抽象类 export abstract class AbstractClassService { abstract doSomething(): void; } // 实现类,通过providedIn注册为根服务 @Injectable({ providedIn: 'root' }) export class ExtendedClassService extends AbstractClassService { doSomething(): void { console.log('执行ExtendedClassService的逻辑'); } } // 在AppModule中配置抽象类与实现类的映射 @NgModule({ providers: [ { provide: AbstractClassService, useClass: ExtendedClassService } ] }) export class AppModule {}
这种方式既保留了抽象解耦的优势,又能让Angular在打包时剔除未被使用的服务代码。
方案2:用useExisting实现更优雅的单例复用
如果你不想在NgModule里维护providers配置,可以先让实现类通过providedIn: 'root'注册为单例服务,再为抽象类配置映射,复用已存在的实现类实例:
// 抽象类 export abstract class AbstractClassService { abstract doSomething(): void; } // 实现类注册为根服务 @Injectable({ providedIn: 'root' }) export class ExtendedClassService extends AbstractClassService { doSomething(): void { console.log('执行ExtendedClassService的逻辑'); } } // 给抽象类配置映射,复用已注册的ExtendedClassService实例 @Injectable({ providedIn: 'root', useExisting: ExtendedClassService }) export abstract class AbstractClassService {}
或者,你也可以在NgModule的providers里用useExisting来配置:
@NgModule({ providers: [ { provide: AbstractClassService, useExisting: ExtendedClassService } ] }) export class AppModule {}
这里useExisting和useClass的核心区别是:useClass会创建一个新的服务实例,而useExisting会复用已注册的ExtendedClassService单例,在大多数场景下更高效。
总结
- 绝对不能通过在
@Injectable({ providedIn: 'root' })里添加provide属性来实现抽象类与实现类的映射,Angular不支持这个配置项。 - 推荐使用上述两种方案之一,既满足依赖注入的抽象解耦需求,又能利用Angular 6+的性能优化特性。
内容的提问来源于stack exchange,提问作者BeetleJuice
相关产品推荐
相关产品推荐

