pomelo源码解析之compnent组件启动
来源:互联网 发布:长得帅的女生知乎 编辑:程序博客网 时间:2024/05/17 06:40
pomelo中的各个功能模块都是以component组件的形式封装的。例如sessionService,channelService等等。
接下来我们来看component如何被启动,废话不多说,直接上源码。
/** * Auto-load bundled components with getters. */fs.readdirSync(__dirname + '/components').forEach(function (filename) { if (!/\.js$/.test(filename)) { return; } var name = path.basename(filename, '.js'); var _load = load.bind(null, './components/', name); Pomelo.components.__defineGetter__(name, _load); Pomelo.__defineGetter__(name, _load);});fs.readdirSync(__dirname + '/filters/handler').forEach(function (filename) { if (!/\.js$/.test(filename)) { return; } var name = path.basename(filename, '.js'); var _load = load.bind(null, './filters/handler/', name); Pomelo.filters.__defineGetter__(name, _load); Pomelo.__defineGetter__(name, _load);});fs.readdirSync(__dirname + '/filters/rpc').forEach(function (filename) { if (!/\.js$/.test(filename)) { return; } var name = path.basename(filename, '.js'); var _load = load.bind(null, './filters/rpc/', name); Pomelo.rpcFilters.__defineGetter__(name, _load);});
首先我们应该了解pomelo.js这个文件的具体作用—初始化所有的配置信息和自动加载所有组件,上面的code就是将所有component已文件名做为name,文件加载得到的function作为value,保存在pomelo对象中。
Application.load = function(name, component, opts) { if(typeof name !== 'string') { opts = component; component = name; name = null; if(typeof component.name === 'string') { name = component.name; } } if(typeof component === 'function') { component = component(this, opts); } if(!name && typeof component.name === 'string') { name = component.name; } if(name && this.components[name]) { // ignore duplicat component logger.warn('ignore duplicate component: %j', name); return; } this.loaded.push(component); if(name) { // components with a name would get by name throught app.components later. this.components[name] = component; } return this;};
之后通过上面的代码,将pomelo中的组件,执行component = component(this, opts);得到组件具体对象,并将对象保存在this.components中 “this.components[name] = component;”。 此处的this就是app = pomelo.createApp();中的app对象。到此为止,app对象中已经保存了我们所有需要component’组件,之后通过start函数,将每一个组件function调用得到组件对象并调用每一个组件对象的start函数。请大家往下看。
Application.start = function(cb) { this.startTime = Date.now(); if(this.state > STATE_INITED) { utils.invokeCallback(cb, new Error('application has already start.')); return; } var self = this; appUtil.startByType(self, function() { appUtil.loadDefaultComponents(self); var startUp = function() { appUtil.optComponents(self.loaded, Constants.RESERVED.START, function(err) { self.state = STATE_START; if(err) { utils.invokeCallback(cb, err); } else { logger.info('%j enter after start...', self.getServerId()); self.afterStart(cb); } }); }; var beforeFun = self.lifecycleCbs[Constants.LIFECYCLE.BEFORE_STARTUP]; if(!!beforeFun) { beforeFun.call(null, self, startUp); } else { startUp(); } });};
此函数为application中的启动函数,有pomelo继承,当我们在app.js中做app.start()时,就是调用的此函数。
此处我们需要了解两个函数appUtil.loadDefaultComponents(self); 和 appUtil.optComponents。
让我们先来看loadDefaultComponents:
module.exports.loadDefaultComponents = function(app) { var pomelo = require('../pomelo'); // load system default components logger.debug('lv:', pomelo) if (app.serverType === Constants.RESERVED.MASTER) { app.load(pomelo.master, app.get('masterConfig')); } else { app.load(pomelo.proxy, app.get('proxyConfig')); if (app.getCurServer().port) { app.load(pomelo.remote, app.get('remoteConfig')); } if (app.isFrontend()) { app.load(pomelo.connection, app.get('connectionConfig')); app.load(pomelo.connector, app.get('connectorConfig')); app.load(pomelo.session, app.get('sessionConfig')); // compatible for schedulerConfig if(app.get('schedulerConfig')) { app.load(pomelo.pushScheduler, app.get('schedulerConfig')); } else { app.load(pomelo.pushScheduler, app.get('pushSchedulerConfig')); } } app.load(pomelo.backendSession, app.get('backendSessionConfig')); app.load(pomelo.channel, app.get('channelConfig')); app.load(pomelo.server, app.get('serverConfig')); } app.load(pomelo.monitor, app.get('monitorConfig'));};
不知道还记不记得上面讲到的,pomelo根据文件名自动加载所有组件,我们可以看到app.load函数的第一个参数是不是在pomelo/lib/component目录下都有这个文件名。事实上,第一个参数就是一个组件函数,有兴趣的还可以去看下app.load的具体实现。总之在这里就将所有的组件函数做了调用得到了组件对象保存在app.components当中。
接下来我们来看optComponents函数:
module.exports.optComponents = function(comps, method, cb) { var i = 0; async.forEachSeries(comps, function(comp, done) { i++; if (typeof comp[method] === 'function') { comp[method](done); } else { done(); } }, function(err) { if (err) { if(typeof err === 'string') { logger.error('fail to operate component, method: %s, err: %j', method, err); } else { logger.error('fail to operate component, method: %s, err: %j', method, err.stack); } } utils.invokeCallback(cb, err); });};
然后我们来看optComponents这个函数的代码compmethod; 此处就是重点。相信大家已经猜到Constants.RESERVED.START 变量就是‘start’字符串。到了这里pomelo的component启动方式。非常清楚。
我们可以查看pomelo的lib/componets目录下所有的文件都是固定的格式,都存在有start()函数,来作为启动函数。
- pomelo源码解析之compnent组件启动
- pomelo源码解析之组件Remote
- pomelo源码解析之通讯协议
- pomelo之server的启动。。
- pomelo组就之server组件分析
- pomelo之proxy组件与rpc客户端
- pomelo之proxy组件与rpc客户端
- pomelo组就之server组件分析
- pomelo之master服务器的启动
- pomelo之master服务器的启动
- activeMQ源码解析之源码调试启动
- Flume-ng源码解析之Channel组件
- Flume-ng源码解析之Source组件
- Flume-ng源码解析之Channel组件
- Flume-ng源码解析之Source组件
- Flume-ng源码解析之Channel组件
- Flume-ng源码解析之Channel组件
- Flume-ng源码解析之Channel组件
- HTTP Status 500
- thinkPHP易错点集合
- nodejs-mysql异步(2)
- 妨碍开发人员获得高性能的三种行为!
- Git基本命令
- pomelo源码解析之compnent组件启动
- 高山算法?其实是贪心啦!
- [Objective-C]关联(objc_setAssociatedObject、objc_getAssociatedObject、objc_removeAssociatedObjects)
- java Map与Object互转
- MySQL存储引擎详解
- Android设备拍照详解
- 管理员登录与退出(自动登录)
- Swift基础之Literal的简单使用
- c#实现简单的即时通讯(2)----客户端