依赖注入库:实现类似Dagger/Hilt的DI框架(229)
在鸿蒙HarmonyOS应用开发中随着业务复杂度的提升模块间的依赖关系往往会变得错综复杂。引入依赖注入DI框架能够实现模块间的彻底解耦提升代码的可测试性与可维护性。针对鸿蒙生态开发者可以选择基于注解的自动化生成方案、轻量级运行时容器或是结合路由框架的跨模块注入方案。一、 自动化代码生成方案injectable inject_generator对于大型工程手动维护依赖树不仅繁琐且极易出错。通过引入injectable与inject_generator开发者可以利用注解在编译期自动完成依赖组装。核心机制利用module、provide、injectable等注解标记依赖通过build_runner在编译期自动扫描并生成*.inject.dart文件构建好单例或工厂的实例化逻辑。鸿蒙适配优势生成的代码是标准的 Dart 实例化调用不涉及运行时反射因此不会带来额外的性能损耗且能在编译期提前发现依赖链条断裂或环形依赖的问题。import { module, provide, injectable } from ohos/injectable; // 1. 定义底层数据库服务模块 module class OhosMainModule { provide provideDb(): OhosDatabase { return new OhosDatabase(); } } // 2. 定义业务服务声明它依赖 OhosDatabase injectable class OhosUserService { private db: OhosDatabase; // 生成器会自动寻找并注入 OhosDatabase constructor(db: OhosDatabase) { this.db db; } fetchUser() { console.info(通过数据库获取用户); } }二、 轻量级运行时 DI 容器weaver如果项目不需要复杂的代码生成weaver是一个极致轻量的 DI 和服务发现框架。核心机制提出了“注册Register- 注入Inject”模型。局部作用域隔离支持weaver.scoped局部作用域容器非常适合在鸿蒙多 HAPHarmonyOS Ability Packages模式下实现模块自治和强弱隔离。import { weaver } from ohos/weaver; // 1. 注册全局单例服务 weaver.registerSingletonAnalyticsService(() new AnalyticsService()); // 2. 创建局部作用域容器例如针对某个特定的业务模块或页面 const scopedContainer weaver.scoped(); scopedContainer.registerFactoryPaymentService(() new PaymentServiceImpl()); // 3. 在业务层获取服务 const analytics weaver.getAnalyticsService(); const payment scopedContainer.getPaymentService();三、 跨模块解耦方案TheRouter 的 ServiceProvider在鸿蒙的组件化开发中跨模块的依赖注入是核心痛点。TheRouter框架提供了ServiceProvider能力来解决这一问题。核心机制支持跨模块依赖注入允许自定义注入项的创建规则与参数。单例缓存支持注入对象缓存多次注入只会 new 一次对象避免内存浪费。import { TheRouter } from ohos/therouter; // 1. 在业务模块中注册服务实现 TheRouter.serviceProvider.register( IUserCenterService, () new UserCenterServiceImpl(), true // true 表示开启单例缓存多次获取只 new 一次 ); // 2. 在基础模块或任意跨模块中获取服务无需 import 实现类 const userCenterService TheRouter.serviceProvider.getIUserCenterService(IUserCenterService); userCenterService?.login(user, password);四、 避坑实践防御循环依赖在复杂的模块化架构中A 依赖 B、B 又依赖 A 会导致“炸弹式堆栈溢出”。应采用延迟初始化Lazy Fetch在业务逻辑内部才调用df.get()或weaver.get()不要在构造函数的第一行就触发全量寻找。异步服务预解析鸿蒙系统中许多底层 API如Preferences.getInstance()、设备传感器初始化都是异步的。如果在 DI 容器就绪前就尝试获取这些服务会导致运行时异常。可使用preResolve注解强制 DI 容器在初始化阶段等待异步服务完成解析。多环境动态适配利用Environment(dev)或Environment(ohos_real)等环境标签可以为同一个接口定义多份实现例如开发环境注入内存缓存MockStorage真机环境注入原生持久化NativeOhosStorage实现跨环境的无缝切换。五、 自动化代码生成实战注解驱动与异步预解析场景在大型工程中利用注解标记依赖由生成器在编译期自动组装依赖树并强制等待底层异步 API如 Preferences初始化完成避免运行时获取空对象。import { module, provide, injectable, preResolve, Environment } from ohos/injectable; // 1. 定义鸿蒙平台模块提供底层数据库与配置服务 module class OhosMainModule { provide provideDb(): OhosDatabase { return new OhosDatabase(); } // 使用 preResolve 强制容器在初始化阶段等待异步服务完成解析 preResolve async getPrefs(): PromisePreferences { return await preferences.get(getContext(this), app_config); } } // 2. 定义业务服务声明它依赖 OhosDatabase injectable class OhosUserService { private db: OhosDatabase; constructor(db: OhosDatabase) { this.db db; } fetchUser() { console.info(通过数据库获取用户); } }六、轻量级运行时 DI 容器weaver 与局部作用域隔离场景在鸿蒙多 HAPHarmonyOS Ability Packages模式下利用weaver实现模块自治。通过局部作用域容器Scoped Container避免全局单例污染实现强弱隔离。import { weaver } from ohos/weaver; // 1. 注册全局单例服务 weaver.registerSingletonAnalyticsService(() new AnalyticsService()); // 2. 创建局部作用域容器例如针对某个特定的业务模块或页面 const scopedContainer weaver.scoped(); scopedContainer.registerFactoryPaymentService(() new PaymentServiceImpl()); // 3. 在业务层获取服务 const analytics weaver.getAnalyticsService(); const payment scopedContainer.getPaymentService();七、跨模块解耦实战TheRouter 的 ServiceProvider场景在组件化架构中基础模块需要调用业务模块的实现但不能直接依赖业务模块。通过 TheRouter 的 ServiceProvider 实现跨模块接口注入与单例缓存。import { TheRouter } from ohos/therouter; // 1. 在业务模块中注册服务实现 TheRouter.serviceProvider.register( IUserCenterService, () new UserCenterServiceImpl(), true // true 表示开启单例缓存多次获取只 new 一次 ); // 2. 在基础模块或任意跨模块中获取服务无需 import 实现类 const userCenterService TheRouter.serviceProvider.getIUserCenterService(IUserCenterService); userCenterService?.login(user, password);