分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 软件开发

解读 IoC 框架 InversifyJS

发布时间:2023-09-06 02:21责任编辑:熊小新关键词:暂无标签

原文链接

InversityJS 是一个 IoC 框架。IoC(Inversion of Control) 包括依赖注入(Dependency Injection) 和依赖查询(Dependency Lookup)。

相比于类继承的方式,控制反转解耦了父类和子类的联系。

案例解析

import 'reflect-metadata'import { inject, injectable, Container } from 'inversify'const container = new Container()@injectable()class PopMusic { ?getName() { ???return '流行音乐' ?}}container.bind('request1').to(PopMusic)@injectable()class ClassicalMusic { ?getName() { ???return '古典音乐' ?}}container.bind('request2').to(ClassicalMusic)@injectable()class Music { ?pm: any ?cm: any ?constructor( ???@inject('request1') popMusic: any, ???@inject('request2') classicalMusic: any) { ???this.pm = popMusic ???this.cm = classicalMusic ?} ?getName() { ???const result = this.pm.getName() + this.cm.getName() ???return result ?}}container.bind('Plan').to(Music)const music: any = container.get('Plan')console.log(music.getName()) // 流行音乐古典音乐

上述案例可以抽象为下图:

虚线表示可以注入,但在代码中没有表现出来。

代码流程可概括如下:

1.将所有相关类(这里指 Music、popMusic、classicMusic) 通过 @injectable 声明进 container 容器;

2.通过 container.get() 获取 container.bind().to(target) 中的目标对象(这里指 Music);

3.如果目标对象中的 constructor() 里有 @inject(), 则将相应的实例(这里指 PopMusic 与 classicalMusic 的实例)当作构造函数的参数‘注入‘;

inject/injectable 相关源码

inject 源码简化如下:

// 这是一个属性装饰器function inject(serviceIdentifier) { ?return function (target, targetKey) { ???const metadataValue = { [targetKey]: [Metadata { key: 'inject', value: serviceIdentifier })] } ???Reflect.defineMetadata('inversify:tagged_props', metadataValue, target.constructor); ?}}

injectable 源码简化如下:

// 这是一个类装饰器function injectable() { ?return function (target) { ???const metadataValue = [] ???Reflect.defineMetadata('inversify:paramtypes', metadataValue, target) ???return target ?}}

从简化版源码中可以看到 inject/injectable 最终是对 Reflect.defineMetadata() 的一个使用。可以将 metadata 看成是一种相对高效的数据结构。

reflect-metadata

InversityJS 深度结合了 reflect-metadata, reflect-metadata 在 Reflect 基础上对其 api 进行了扩展。

metadata 本质上是一个 WeakMap 对象。扩展:Map 和 WeakMap 的区别

Reflect.defineMetadata(metadataKey, metadataValue, target[, propertyKey]) 简化版实现如下:

const Metadata = new WeakMap()function defineMetadata(metadataKey, metadataValue, target, propertyKey) { ?metadataMap = new Map() ?metadataMap.set(metadataKey, metadataValue) ?targetMetadata = new Map() ?targetMetadata.set(propertyKey, metadataMap) ?Metadata.set(target, targetMetadata)}

Reflect.getOwnMetadata(metadataKey, target[, propertyKey]) 简化版实现如下:

function getOwnMetadata(metadataKey, target, propertyKey) { ?var targetMetadata = Metadata.get(target) ?var metadataMap = targetMetadata.get(propertyKey) ?return metadataMap.get(metadataKey)}

其数据结构可表示如下:

WeakMap { ?target: Map { ???propertyKey: Map { ?????metadataKey: metadataValue ???} ?}}

相关链接

  • Architecture overview

解读 IoC 框架 InversifyJS

原文地址:https://www.cnblogs.com/MuYunyun/p/9922888.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved