当前位置: 首页 > news >正文

依赖注入框架 InversifyJS

背景

面向对象有五大原则:单一职责、开闭原则、里氏替换、接口分离和依赖反转。依赖反转(Dependency Inversion),实体应该依赖于抽象而不是实现。也就是说高层次模块,不应该依赖于低层次模块,而是应该基于抽象。

WebIDE 是函数计算团队研发的一款产品,为了解决函数计算本地环境差异和配置繁琐的问题。WebIDE 前端是 monorepo 风格的项目,即插件化构建 WebIDE 前端。插件之间存在依赖关系。构建、扩展和以及使用一个插件将是一个复杂的问题,而且对使用插件的开发人员不透明。通过使用 inversify 就能很简单的实现。通过 inversify 能很容的实现插件的构建、扩展和使用。

  • 创建。将服务类注入到容器中
  • 替换。通过 rebind api 可以在其他模块中从新绑定某个服务
  • 使用。在类中通过装饰器注入需要使用的服务,服务的具体实现不需要关心,容器为我们管理

需要了解 WebIDE 详情,请移步:WebIDE 使用手册

介绍

InversifyJS 是一个轻量级的依赖注入框架,大小只有 4KB,可以用于 Javascript 应用中。

安装

由于 InversifyJS 用到了反射来获取装饰器的相关元数据,所以需要额外安装库 reflect-metadata

npm install inversify reflect-metadata --save

另外,InversifyJS 要求 Typescript >= 2.0 并且需要配置如下编译参数:

{
    "compilerOptions": {
        "target": "es5",
        "lib": ["es6", "dom"],
        "types": ["reflect-metadata"],
        "module": "commonjs",
        "moduleResolution": "node",
        "experimentalDecorators": true,
        "emitDecoratorMetadata": true
    }
}

使用

步骤 1:定义接口

// file interfaces.ts

// 定义服务对象标识
export const Warrior = Symbol.for('Warrior');
export const Weapon = Symbol.for('Weapon');
export const ThrowableWeapon = Symbol.for('ThrowableWeapon');

export interface Warrior {
    fight(): string;
    sneak(): string;
}

export interface Weapon {
    hit(): string;
}

export interface ThrowableWeapon {
    throw(): string;
}

步骤 2:定义依赖

// file entities.ts

import { injectable, inject } from 'inversify';
import 'reflect-metadata';
import { Weapon, ThrowableWeapon, Warrior } from './interfaces';

@injectable()
export class Katana implements Weapon {
    public hit() {
        return "cut!";
    }
}

@injectable()
export class Shuriken implements ThrowableWeapon {
    public throw() {
        return "hit!";
    }
}

@injectable()
export class Ninja implements Warrior {

    public constructor(
        @inject(Weapon) protected katana: Weapon,
        @inject(ThrowableWeapon) protected shuriken: ThrowableWeapon
    ) {}

    public fight() { return this.katana.hit(); }
    public sneak() { return this.shuriken.throw(); }

}

步骤 3:创建并配置 IOC 容器

// file inversify.config.ts

import { Container } from "inversify";
import { Warrior, Weapon, ThrowableWeapon } from "./interfaces";
import { Ninja, Katana, Shuriken } from "./entities";

const myContainer = new Container();
myContainer.bind<Warrior>(Warrior).to(Ninja);
myContainer.bind<Weapon>(Weapon).to(Katana);
myContainer.bind<ThrowableWeapon>ThrowableWeapon).to(Shuriken);

export { myContainer };

步骤4:依赖解析

import { myContainer } from "./inversify.config";
import { Warrior } from "./interfaces";

const ninja = myContainer.get<Warrior>(Warrior);

expect(ninja.fight()).eql("cut!"); // true
expect(ninja.sneak()).eql("hit!"); // true

小结

如果你熟悉 Spring,Spring 很多特性在 Inversify 中可以找到,如果你的项目规模比较大,可以采用 monorepo 多包结构来构建项目。每一个包(模块)包含一个 ContainerModule 容器管理本模块依赖,然后在项目入口对所有的模块容器进行统一加载。

相关文章:

  • 10.30T2 二分+前缀和(后缀和)
  • 数据流的压缩、编码及传递困扰
  • Linux基础命令---mkisofs
  • Linux iptables开放特定端口
  • (原创)Stanford Machine Learning (by Andrew NG) --- (week 9) Anomaly DetectionRecommender Systems...
  • 线段树模板
  • KVO的使用
  • 自动化测试
  • Unicode编码字符 转换成汉字
  • 简单用户管理系统(P-05)
  • typedef 与指针、多维数组
  • 32、mysql数据库增删改查
  • Android -- 保存文件
  • ORACLE EXECUTE IMMEDIATE 用法详解
  • SpringMVC使用@ResponseBody输出字符串时遇到的乱码问题及解决办法
  • 分享一款快速APP功能测试工具
  • [deviceone开发]-do_Webview的基本示例
  • 【跃迁之路】【477天】刻意练习系列236(2018.05.28)
  • 2018以太坊智能合约编程语言solidity的最佳IDEs
  • 345-反转字符串中的元音字母
  • echarts花样作死的坑
  • ES6系统学习----从Apollo Client看解构赋值
  • Flex布局到底解决了什么问题
  • HomeBrew常规使用教程
  • JavaScript异步流程控制的前世今生
  • js中的正则表达式入门
  • mysql外键的使用
  • mysql中InnoDB引擎中页的概念
  • Node项目之评分系统(二)- 数据库设计
  • Travix是如何部署应用程序到Kubernetes上的
  • Vue学习第二天
  • 从@property说起(二)当我们写下@property (nonatomic, weak) id obj时,我们究竟写了什么...
  • 紧急通知:《观止-微软》请在经管柜购买!
  • 开源中国专访:Chameleon原理首发,其它跨多端统一框架都是假的?
  • 看域名解析域名安全对SEO的影响
  • 什么软件可以提取视频中的音频制作成手机铃声
  • 用Python写一份独特的元宵节祝福
  • 我们雇佣了一只大猴子...
  • 昨天1024程序员节,我故意写了个死循环~
  • !!java web学习笔记(一到五)
  • #100天计划# 2013年9月29日
  • (2)nginx 安装、启停
  • (22)C#传智:复习,多态虚方法抽象类接口,静态类,String与StringBuilder,集合泛型List与Dictionary,文件类,结构与类的区别
  • (八)Docker网络跨主机通讯vxlan和vlan
  • (第61天)多租户架构(CDB/PDB)
  • (附源码)springboot工单管理系统 毕业设计 964158
  • (附源码)springboot建达集团公司平台 毕业设计 141538
  • (一) springboot详细介绍
  • (已解决)报错:Could not load the Qt platform plugin “xcb“
  • (轉貼) 資訊相關科系畢業的學生,未來會是什麼樣子?(Misc)
  • .NET Core实战项目之CMS 第十二章 开发篇-Dapper封装CURD及仓储代码生成器实现
  • .NET 使用 ILRepack 合并多个程序集(替代 ILMerge),避免引入额外的依赖
  • .NET命令行(CLI)常用命令
  • .NET牛人应该知道些什么(2):中级.NET开发人员
  • @entity 不限字节长度的类型_一文读懂Redis常见对象类型的底层数据结构