JavaScript系列(43)--依赖注入系统实现详解

JavaScript依赖注入系统实现详解 💉

今天,让我们深入探讨JavaScript的依赖注入系统实现。依赖注入是一种设计模式,它通过将依赖关系的创建和管理从代码中分离出来,提高了代码的可维护性和可测试性。

依赖注入基础概念 🌟

💡 小知识:依赖注入是控制反转(IoC)的一种实现方式,它将对象的创建和依赖关系的处理交给外部容器来管理,而不是在对象内部直接创建依赖对象。

基本实现 📊

javascript 复制代码
// 1. 基础依赖注入容器
class Container {
    constructor() {
        this.services = new Map();
        this.singletons = new Map();
    }
    
    // 注册服务
    register(name, definition, dependencies = []) {
        this.services.set(name, { definition, dependencies });
    }
    
    // 注册单例服务
    singleton(name, definition, dependencies = []) {
        this.register(name, definition, dependencies);
        this.singletons.set(name, null);
    }
    
    // 解析服务
    resolve(name) {
        const service = this.services.get(name);
        if (!service) {
            throw new Error(`Service ${name} not found`);
        }
        
        // 检查是否是单例且已存在实例
        if (this.singletons.has(name)) {
            const singletonInstance = this.singletons.get(name);
            if (singletonInstance) {
                return singletonInstance;
            }
        }
        
        // 解析依赖
        const dependencies = service.dependencies.map(dep => this.resolve(dep));
        
        // 创建实例
        const instance = typeof service.definition === 'function'
            ? new service.definition(...dependencies)
            : service.definition;
            
        // 如果是单例,保存实例
        if (this.singletons.has(name)) {
            this.singletons.set(name, instance);
        }
        
        return instance;
    }
}

// 2. 装饰器支持
function Injectable() {
    return function(target) {
        // 保存原始构造函数
        target.injectable = true;
        return target;
    };
}

function Inject(name) {
    return function(target, propertyKey) {
        // 在原型上定义属性
        const metadata = Reflect.getMetadata('inject', target) || {};
        metadata[propertyKey] = name;
        Reflect.defineMetadata('inject', metadata, target);
    };
}

// 3. 依赖解析器
class DependencyResolver {
    constructor(container) {
        this.container = container;
    }
    
    // 解析类的依赖
    resolveClass(target) {
        const metadata = Reflect.getMetadata('inject', target.prototype);
        const dependencies = {};
        
        if (metadata) {
            for (const [key, name] of Object.entries(metadata)) {
                dependencies[key] = this.container.resolve(name);
            }
        }
        
        return dependencies;
    }
    
    // 创建实例并注入依赖
    createInstance(target) {
        const dependencies = this.resolveClass(target);
        const instance = new target();
        
        Object.assign(instance, dependencies);
        return instance;
    }
}

高级功能实现 🚀

javascript 复制代码
// 1. 生命周期管理
class LifecycleManager {
    constructor() {
        this.hooks = new Map();
    }
    
    // 注册生命周期钩子
    registerHook(service, hook) {
        if (!this.hooks.has(service)) {
            this.hooks.set(service, []);
        }
        this.hooks.get(service).push(hook);
    }
    
    // 执行初始化钩子
    async initialize(service) {
        const hooks = this.hooks.get(service) || [];
        for (const hook of hooks) {
            if (hook.onInit) {
                await hook.onInit();
            }
        }
    }
    
    // 执行销毁钩子
    async destroy(service) {
        const hooks = this.hooks.get(service) || [];
        for (const hook of hooks) {
            if (hook.onDestroy) {
                await hook.onDestroy();
            }
        }
    }
}

// 2. 作用域管理
class ScopeManager {
    constructor() {
        this.scopes = new Map();
        this.currentScope = null;
    }
    
    // 创建新作用域
    createScope(name) {
        const scope = new Container();
        this.scopes.set(name, scope);
        return scope;
    }
    
    // 进入作用域
    enterScope(name) {
        const scope = this.scopes.get(name);
        if (!scope) {
            throw new Error(`Scope ${name} not found`);
        }
        this.currentScope = scope;
        return scope;
    }
    
    // 退出作用域
    exitScope() {
        this.currentScope = null;
    }
    
    // 在当前作用域中解析服务
    resolve(name) {
        if (!this.currentScope) {
            throw new Error('No active scope');
        }
        return this.currentScope.resolve(name);
    }
}

// 3. 异步依赖处理
class AsyncContainer extends Container {
    constructor() {
        super();
        this.asyncServices = new Map();
    }
    
    // 注册异步服务
    async registerAsync(name, factory) {
        this.asyncServices.set(name, factory);
    }
    
    // 异步解析服务
    async resolveAsync(name) {
        // 检查是否是异步服务
        if (this.asyncServices.has(name)) {
            const factory = this.asyncServices.get(name);
            return await factory();
        }
        
        // 否则使用同步解析
        return this.resolve(name);
    }
    
    // 批量解析异步服务
    async resolveAll(names) {
        return Promise.all(names.map(name => this.resolveAsync(name)));
    }
}

实际应用场景 💼

javascript 复制代码
// 1. 服务定义和注入
@Injectable()
class UserService {
    constructor(database) {
        this.database = database;
    }
    
    async getUsers() {
        return this.database.query('SELECT * FROM users');
    }
}

@Injectable()
class AuthService {
    @Inject('userService')
    userService;
    
    async authenticate(username, password) {
        const user = await this.userService.findByUsername(username);
        return user && user.password === password;
    }
}

// 2. API服务注入
@Injectable()
class ApiService {
    constructor(config) {
        this.baseUrl = config.apiUrl;
    }
    
    async request(method, path, data) {
        const response = await fetch(`${this.baseUrl}${path}`, {
            method,
            headers: {
                'Content-Type': 'application/json'
            },
            body: data ? JSON.stringify(data) : undefined
        });
        
        return response.json();
    }
}

// 3. 业务逻辑注入
@Injectable()
class OrderService {
    constructor(
        @Inject('userService') userService,
        @Inject('paymentService') paymentService,
        @Inject('notificationService') notificationService
    ) {
        this.userService = userService;
        this.paymentService = paymentService;
        this.notificationService = notificationService;
    }
    
    async createOrder(userId, items) {
        const user = await this.userService.getUser(userId);
        const payment = await this.paymentService.processPayment(user, items);
        
        if (payment.success) {
            await this.notificationService.sendOrderConfirmation(user, items);
            return { success: true, orderId: payment.orderId };
        }
        
        return { success: false, error: payment.error };
    }
}

性能优化技巧 ⚡

javascript 复制代码
// 1. 依赖缓存
class CachedContainer extends Container {
    constructor() {
        super();
        this.cache = new Map();
    }
    
    resolve(name) {
        if (this.cache.has(name)) {
            return this.cache.get(name);
        }
        
        const instance = super.resolve(name);
        this.cache.set(name, instance);
        return instance;
    }
    
    clearCache() {
        this.cache.clear();
    }
    
    invalidate(name) {
        this.cache.delete(name);
    }
}

// 2. 延迟加载
class LazyContainer extends Container {
    constructor() {
        super();
        this.factories = new Map();
    }
    
    registerLazy(name, factory) {
        this.factories.set(name, factory);
    }
    
    resolve(name) {
        if (this.factories.has(name)) {
            const factory = this.factories.get(name);
            const instance = factory();
            this.register(name, instance);
            this.factories.delete(name);
            return instance;
        }
        
        return super.resolve(name);
    }
}

// 3. 批量注册优化
class BatchContainer extends Container {
    constructor() {
        super();
        this.batchQueue = [];
    }
    
    startBatch() {
        this.batchQueue = [];
    }
    
    register(name, definition, dependencies = []) {
        this.batchQueue.push({ name, definition, dependencies });
    }
    
    commitBatch() {
        for (const registration of this.batchQueue) {
            super.register(
                registration.name,
                registration.definition,
                registration.dependencies
            );
        }
        this.batchQueue = [];
    }
}

最佳实践建议 💡

  1. 依赖注入模式
javascript 复制代码
// 1. 构造函数注入
class UserController {
    constructor(userService, authService) {
        this.userService = userService;
        this.authService = authService;
    }
}

// 2. 属性注入
class OrderController {
    @Inject('orderService')
    orderService;
    
    @Inject('userService')
    userService;
}

// 3. 方法注入
class ProductController {
    @Inject('productService')
    setProductService(service) {
        this.productService = service;
    }
}

结语 📝

依赖注入是一种强大的设计模式,它能够帮助我们构建更加灵活和可维护的应用。通过本文,我们学习了:

  1. 依赖注入的基本概念和实现
  2. 高级功能如生命周期管理和作用域
  3. 实际应用场景和示例
  4. 性能优化技巧
  5. 最佳实践和设计模式

💡 学习建议:在使用依赖注入时,要注意平衡灵活性和复杂性。不是所有的依赖关系都需要通过注入来管理,要根据实际需求选择合适的方案。


如果你觉得这篇文章有帮助,欢迎点赞收藏,也期待在评论区看到你的想法和建议!👇

终身学习,共同成长。

咱们下一期见

💻

相关推荐
2401_8582861120 分钟前
L29.【LeetCode笔记】丢失的数字
c语言·开发语言·算法
爱上大树的小猪39 分钟前
【前端】Electron入门开发教程,从介绍Electron到基础引用以及部分深度使用,附带常见的十个报错问题的解决方案和代码优化。
前端·javascript·electron
艺杯羹1 小时前
二级C语言题解:孤独数、找最长子串、返回两数组交集
c语言·开发语言·数据结构·算法
比特在路上1 小时前
ListOJ13:环形链表(判断是否为环形链表)
c语言·开发语言·数据结构·链表
weisian1511 小时前
消息队列篇--扩展篇--码表及编码解码(理解字符字节和二进制,了解ASCII和Unicode,了解UTF-8和UTF-16,了解字符和二进制等具体转化过程等)
java·开发语言
xianwu5431 小时前
反向代理模块。。
开发语言·网络·数据库·c++·mysql
呦呦鹿鸣Rzh1 小时前
实现标题-超链接
java·前端·javascript
Super毛毛穗1 小时前
GeoJSON 数据
javascript·gis·geojson
{⌐■_■}1 小时前
【Validator】字段验证器struct与多层级验证,go案例
开发语言·信息可视化·golang
fly spider1 小时前
每日 Java 面试题分享【第 13 天】
java·开发语言·面试