跳转到主内容
极星编程网:以代码为星,赴技术山海!

JavaScript依赖注入_IoC容器设计与实现

首先实现一个简易IoC容器,通过bind、singleton和resolve方法管理依赖;利用$inject声明构造函数依赖,实现自动注入;支持类、工厂函数和值绑定,提升灵活性。 依赖注入(Dependency Injection, DI)和控制反转(Inversion of Control, IoC)是现代软件设计中解耦组件、提升可测试性和可维护性的关键模式。在JavaScript中,虽然语言本身不内置DI机制,但通过手动实现或使用轻量容器,可以很好地支持这一思想。本文将带你从零开始设计并实现一个简易但实用的IoC容器。 什么是依赖注入与IoC 控制反转是指将对象创建和依赖管理的责任从类内部转移到外部容器。依赖注入是实现IoC的一种方式,即通过构造函数、方法或属性将依赖“注入”到目标对象中,而不是在类内部直接实例化。 例如,一个服务类不需要自己创建数据库连接,而是由外部传入:
class UserService { constructor(userRepository) { this.userRepository = userRepository; } getUser(id) { return this.userRepository.findById(id); } }
这样,UserService不再关心UserRepository如何创建,只依赖其接口行为,实现了松耦合。 立即学习 “ Java免费学习笔记(深入) ”; 设计一个简单的IoC容器 IoC容器的核心职责是:注册依赖、解析依赖、管理生命周期。我们可以设计一个Container类来实现这些功能。 基本能力包括: bind :绑定一个标识符到具体的类或工厂函数 singleton :绑定为单例,只创建一次 resolve :根据标识符创建实例,并自动注入其依赖 我们通过构造函数参数的类型提示(或手动标记)来实现自动依赖解析。 Eclipse导入Android或其他的JAVA项目的正确方法 WORD版 本文档主要讲述的是Eclipse导入Android或其他的JAVA项目的正确方法;希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看 下载 实现依赖解析逻辑 JavaScript不支持运行时类型反射,但我们可以通过一些约定来模拟。常见做法是使用
$inject
静态属性或装饰器来声明依赖。 示例实现:
class Container { constructor() { this.bindings = new Map(); this.singletons = new Map(); } bind(token, implementation) { this.bindings.set(token, { implementation, singleton: false }); } singleton(token, implementation) { this.bindings.set(token, { implementation, singleton: true }); } resolve(token) { if (this.singletons.has(token)) { return this.singletons.get(token); } const binding = this.bindings.get(token); if (!binding) { throw new Error(`No binding found for ${token.name || token}`); } const { implementation, singleton } = binding; const dependencies = implementation.$inject || []; const instances = dependencies.map(dep => this.resolve(dep)); const instance = new implementation(...instances); if (singleton) { this.singletons.set(token, instance); } return instance; } }
使用方式:
class UserRepository { } UserRepository.$inject = []; class UserService { constructor(userRepository) { this.userRepository = userRepository; } } UserService.$inject = [UserRepository]; const container = new Container(); container.bind(UserRepository, UserRepository); container.bind(UserService, UserService); const userService = container.resolve(UserService);
支持工厂函数与值绑定 除了类,容器还应支持值绑定和工厂函数,以满足不同场景。 扩展bind方法:
bindValue(token, value) { this.bindings.set(token, { implementation: () => value, singleton: true }); } bindFactory(token, factoryFn) { this.bindings.set(token, { implementation: factoryFn, singleton: false }); }
这样可以注入配置、API客户端等非类实例。 基本上就这些。一个轻量的IoC容器不需要复杂的设计,关键是清晰的API和可靠的依赖解析。你可以在此基础上增加 作用域 、 异步加载 、模块化注册等功能。核心思想是:让对象专注于行为,把创建交给容器。

相关文章