解读 IoC 框架 InversifyJS

栏目: 后端 · 发布时间: 7年前

内容简介:InversityJS 是一个 IoC 框架。IoC(Inversion of Control) 包括依赖注入(Dependency Injection) 和依赖查询(Dependency Lookup)。相比于类继承的方式,控制反转解耦了父类和子类的联系。

解读 IoC 框架 InversifyJS

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()) // 流行音乐古典音乐

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

解读 IoC 框架 InversifyJS

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

代码流程可概括如下:

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
    }
  }
}

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。

The Art and Science of CSS

The Art and Science of CSS

Jonathan Snooks、Steve Smith、Jina Bolton、Cameron Adams、David Johnson / SitePoint / March 9, 2007 / $39.95

Want to take your CSS designs to the next level? will show you how to create dozens of CSS-based Website components. You'll discover how to: # Format calendars, menus and table of contents usin......一起来看看 《The Art and Science of CSS》 这本书的介绍吧!

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具