设为首页收藏本站

LUPA开源社区

 找回密码
 注册
文章 帖子 博客
LUPA开源社区 首页 业界资讯 技术文摘 查看内容

当IoC遇见了Node.js

2014-6-6 12:00| 发布者: joejoe0332| 查看: 4119| 评论: 0|原作者: 倪震洋|来自: Infoq

摘要: 一个简单的例子:在例子中,汽车(car)需要依赖轮子(wheel)和发动机(engine)才能跑起来。为了处理好这一关系,必须首先人为的通过require把engine和wheel引入进来,然后通过new操作实例化,这样car才能真正的ru ...


  更多IoC的功能


  scope 定义


  IoC中可以定义scope,可支持singleton和prototype两种scope,默认情况下scope是singleton的。scope其实对应着常见的两种设计模式,即单例模式(singleton)和多例模式(prototype)。


singleton:

{    "name": "simple",    "beans": [{        "id": "car",        "func": "car",        "scope": "singleton"    }]}
var car1 = bearcat.getBean('car');var car2 = bearcat.getBean('car');// car1 与 car2 是同一个实例对象


  prototype:

{    "name": "simple",    "beans": [{        "id": "car",        "func": "car",        "scope": "prototype"    }]}
var car1 = bearcat.getBean('car');var car2 = bearcat.getBean('car');// car1 与 car2 不是同一个实例对象 


  生命周期回调

  初始化与销毁操作在Node.js开发中是非常常见的。


  初始化方法

var Car = function() {    this.num = 0;}Car.prototype.init = function() {    console.log('init car...');    this.num = 1;    return 'init car';}Car.prototype.run = function() {    console.log('run car...');    return 'car ' + this.num;}module.exports = Car;


  car现在需要在实例化之后执行一个init方法来做些初始化的工作,那么在IoC中可以如下定义:

{    "name": "simple_init_method",    "beans": [{        "id": "car",        "func": "car",        "scope": "prototype",        "init": "init"    }]}


  销毁方法


  销毁方法在处理数据库链接等场景时非常有用。一个系统在shutdown的时候,平滑优雅的关闭就需要处理一些资源释放、完成未完成的任务等工作:

var Car = function() {};Car.prototype.destroy = function() {    console.log('destroy car...');    return 'destroy car';};Car.prototype.run = function() {    console.log('run car...');    return 'car';};module.exports = Car;


  当car结束生命的时候,需要执行一个destroy方法来释放资源,那么在IoC中可以如下定义:


{    "name": "simple_destroy_method",    "beans": [{        "id": "car",        "func": "car",        "destroy": "destroy"    }]}


  异步初始化方法


  众所周知,Node.js中异步调用是非常平常的,比如初始化一个MySQL或者Redis的连接都是异步的,那么异步的初始化方法也就不可避免。而且在某些场景下,必须要求异步操作完成后,才能继续另外一个操作,这就要求保证两者之间的顺序性。在 Bearcat IoC中,你可以配置orderasync来完成这样的初始化需求:


var Car = function() {    this.num = 0;}Car.prototype.init = function() {    console.log('init car...');    this.num = 1;}Car.prototype.run = function() {    console.log('run car...');    return 'car ' + this.num;}module.exports = Car;
var Wheel = function() {}Wheel.prototype.init = function(cb) {    console.log('init wheel...');    setTimeout(function() {        console.log('asyncInit setTimeout');        cb();    }, 1000);}Wheel.prototype.run = function() {    console.log('run wheel...');    return 'wheel';}module.exports = Wheel;


  在这个简单的例子中,wheel有一个异步的初始化方法,它必须在car初始化之前调用,那么你就可以在context.json配置中配置wheel为async的,且order的值比car的要小,以表明wheel要在car之前初始化:


{    "name": "simple_async_init",    "beans": [{        "id": "car",        "func": "car",        "init": "init",        "order": 2    }, {        "id": "wheel",        "func": "wheel",        "async": true,        "init": "init",        "order": 1    }]}


  IoC 实战


  随心所欲的单元测试


  在单元测试中,很多情况下需要构造一个对象的 mock 对象出来,然后被测试的对象调用这个mock对象来进行单元测试。但是在没有IoC之前,由于测试对象和mock原对象之间往往是紧密耦合的,那么要完成这样的操作,要么就是修改mock原对象的代码,要么就是修改测试对象的代码,但这样都不是最佳的实践。比如说一个基于express的web应用里面有一个userController,它依赖于userService:


var userService = require('../service/user-service');exports.allUsers = function (req, res, next) {  userService.getUsers(function (err, users) {    if (err) {      return next(err);    }    res.json(users);  });};


  这时,如果想构造一个userService的mock对象mockUserService,并且在userController里面require进来进行测试的话,就需要修改userController里面的代码,比如这样子:


//var userService = require('../service/user-service');var userService = require('../service/mock-user-service');exports.allUsers = function (req, res, next) {  userService.getUsers(function (err, users) {    if (err) {      return next(err);    }    res.json(users);  });};


  而通过IoC,这一切就变得非常的简单,无需修改代码即可完成。


  在IoC容器管理下,依赖关系是通过对象给IoC容器的描述来完成的,因此,只需要修改context.json元数据配置,即可完成原始对象和mock对象之间的无缝切换:


{    "name": "simple_unit_test",    "beans": [{        "id": "userController",        "func": "userController",        "props": [{          "name": "userService",          "ref": "userService"        }]    }]}


  改成如下所示的test-context.json即可。单元测试的时候,使用test-context.json来作为IoC容器的配置,既不影响开发,也可以完成测试工作,相当的便捷:


{    "name": "simple_unit_test",    "beans": [{        "id": "userController",        "func": "userController",        "props": [{          "name": "userService",          "ref": "mockUserService"        }]    }]}



酷毙

雷人

鲜花

鸡蛋

漂亮
  • 快毕业了,没工作经验,
    找份工作好难啊?
    赶紧去人才芯片公司磨练吧!!

最新评论

关于LUPA|人才芯片工程|人才招聘|LUPA认证|LUPA教育|LUPA开源社区 ( 浙B2-20090187 浙公网安备 33010602006705号   

返回顶部