Angular中如何从对等模块重写Provider且无需修改AppModule?
问题描述
现有两个库模块和一个应用模块,代码如下:
LibAModule 及关联组件
import { Something} from 'services/Something'; import { SomeComponent} from 'components/SomeComponent'; @NgModule({ declarations: [ SomeComponent, ], providers: [ Something, ], ... }) export class LibAModule { } // SomeComponent 实现 import { Something} from '../services/Something'; @Component({...}) export class SomeComponent { public constructor (private readonly _something: Something) { } }
LibBModule
import { LibAModule, Something } from 'libraryA'; @NgModule({ providers: [ { provide: Something, useClass: SomethingAwesome, } ], ... }) export class LibBModule { }
AppModule
import { LibAModule } from 'libraryA'; import { LibBModule } from 'libraryB'; @NgModule({ imports: [ LibAModule, LibBModule, ], ... }) export class AppModule { }
当前配置下,SomeComponent 注入的是 Something 实例,需求是让 SomeComponent 注入 SomethingAwesome 实例,且不修改AppModule。已知直接在AppModule的providers中添加重写配置可生效,但希望通过修改LibBModule实现自动覆盖。
解决方案
可以通过修改LibBModule实现需求,核心利用Angular注入器的优先级规则:后注册到根注入器的同名Provider会覆盖先注册的,具体实现方式如下:
调整LibBModule的导入与导出逻辑
修改LibBModule,主动导入LibAModule并导出它,同时保留Provider覆盖配置:
import { LibAModule, Something } from 'libraryA'; @NgModule({ imports: [LibAModule], // 主动导入LibAModule,确保其Provider先注册 providers: [ { provide: Something, useClass: SomethingAwesome, } ], exports: [LibAModule] // 导出LibAModule,保证AppModule能正常使用其中的组件 }) export class LibBModule { }
当AppModule导入LibBModule时,LibAModule的Provider会先被注册到根注入器,随后LibBModule的覆盖配置会立即替换掉原有Provider。即使AppModule仍保留对LibAModule的导入,由于LibBModule的Provider注册顺序更靠后,最终生效的依然是SomethingAwesome。
注意事项
如果Something类使用了@Injectable({providedIn: 'root'})装饰器,模块级的Provider无法覆盖它。此时需要确保Something的装饰器中移除providedIn: 'root',仅通过模块的providers数组注册,才能被后续的Provider覆盖。
内容的提问来源于stack exchange,提问作者wertzui
相关产品推荐
相关产品推荐

