bean/swoft
中的代码如下:
// 引入bootstrap.php文件
// 实际上bootstrap.php只干了一件事:引入/vendor/autoload.php
// 由autoload.php来加载项目中的库类
// Bootstrap
require_once __DIR__ . '/bootstrap.php';
// 设置最大协程数量
SwooleCoroutine::set([
'max_coroutine' => 300000,
]);
// 实例化application
// 调用application的run方法执行应用
// run方法声明在Swoft\Contract\ApplicationInterface
// 实现在Swoft\SwoftApplication
// Run application
(new AppApplication())->run();
AppApplication的实现很简单:
class Application extends SwoftApplication
{
protected function beforeInit(): void
{
parent::beforeInit();
// 设置时区
// you can init php setting.
date_default_timezone_set('Asia/Shanghai');
}
/**
* @return array
*/ public function getCLoggerConfig(): array
{
$config = parent::getCLoggerConfig();
// False: Dont print log to terminal
// 将控制台输出打开
$config['enable'] = true;
return $config;
}
}
里面只是重写了父类SwoftApplication的beforeInit方法和`
getCLoggerConfig方法.
所以实例化application的操作还是在父类SwoftApplication的构造方法中完成的,先看父类的构造方法代码:
public function __construct(array $config = [])
{
// 第一件事情是检查当前的运行环境
// 后附检查运行时环境的代码
// 主要检测PHP版本、swoole版本以及是否加载了有冲突的扩展
// Check runtime env
SwoftHelper::checkRuntime();
// Storage as global static property.
// 将当前实例保存在Swoft类的静态属性上
Swoft::$app = $this;
// 调用(触发)beforeInit函数(事件)
// 在Application的beforeInit中先调用了父类的beforeInit
// 父类中检测并定义了是否在Phar包中执行的常量IN_PHAR
// 然后子类中设置了当前时区
// Before init
$this->beforeInit();
// 初始化控制台日志logger
// 后附日志初始化代码
// Init console logger
$this->initCLogger();
// 设置额外属性 此处因为未传构造参数 所以不会执行
// Can setting properties by array
if ($config) {
ObjectHelper::init($this, $config);
}
// 初始化应用
// 后附实现代码
// Init application
$this->init();
// afterInit方法(事件)调用(触发)
// 如果是在phar环境下面会设置runtime目录,未做其它额外操作
// After init
$this->afterInit();
}
运行时环境检测代码:
public static function checkRuntime(string $minPhp = '7.1', string $minSwoole = '4.4.1'): void
{
// 检测php版本是否大于7.1 不满足条件就抛出RuntimeException
if (version_compare(PHP_VERSION, $minPhp, '<')) {
throw new RuntimeException('Run the server requires PHP version > ' . $minPhp . '! current is ' . PHP_VERSION);
}
// 检测是否加载了swoole扩展
if (!extension_loaded('swoole')) {
throw new RuntimeException("Run the server, extension 'swoole' is required!");
}
// 检测swoole扩展版本是否大于4.4.1
if (version_compare(SWOOLE_VERSION, $minSwoole, '<')) {
throw new RuntimeException('Run the server requires swoole version > ' . $minSwoole . '! current is ' . SWOOLE_VERSION);
}
// 冲突扩展
$conflicts = [
'blackfire',
'xdebug',
'uopz',
'xhprof',
'zend',
'trace',
];
// 遍历冲突扩展 如果检测到加载了这些冲突扩展 则抛出异常
foreach ($conflicts as $ext) {
if (extension_loaded($ext)) {
throw new RuntimeException("The extension of '{$ext}' must be closed, otherwise swoft will be affected!");
}
}
}
SwoftApplication的beforeInit:
protected function beforeInit(): void
{
// Check phar env
// 检测运行环境是否为phar包
if (!defined('IN_PHAR')) {
define('IN_PHAR', false);
}
}
日志初始化代码:
private function initCLogger(): void
{
// 获取日志配置(此处为父类的返回)
// [
// 'name' => 'swoft',
// 'enable' => true,
// 'output' => true,
// 'levels' => '',
// 'logFile' => ''
// ]
// Console logger config
// 子类中再次将enable设置为true
$config = $this->getCLoggerConfig();
// 初始化控制台logger
// swoft的CLog使用monolog,在monolog的基础上
// 封装了getTrace方法,方便swoole的调试
// 后附代码
// Init console log
CLog::init($config);
}
CLog::init代码:
public static function init(array $config): void
{
// self::$cLogger不为null表示已经有logger,无需再次初始化
if (self::$cLogger !== null) {
return;
}
// config配置
$name = $config['name'] ?? '';
$enable = $config['enable'] ?? true;
$output = $config['output'] ?? true;
$levels = $config['levels'] ?? '';
$logFile = $config['logFile'] ?? '';
// 此处使用monolog的LineFormatter作为后续
// CEchoHandler和CFileHandler的组件
$lineFormatter = new LineFormatter();
// 初始化CEchoHandler并设置
$cEchoHandler = new CEchoHandler();
$cEchoHandler->setFormatter($lineFormatter);
$cEchoHandler->setLevels($levels);
$cEchoHandler->setOutput($output);
// 初始化CFileHandler并设置
$cFileHandler = new CFileHandler();
$cFileHandler->setFormatter($lineFormatter);
$cFileHandler->setLevels($levels);
$cFileHandler->setLogFile($logFile);
// 初始化CLogger 该logger继承于monolog
$cLogger = new CLogger();
$cLogger->setName($name);
$cLogger->setEnable($enable);
$cLogger->setHandlers([$cEchoHandler, $cFileHandler]);
// 将初始化好的控制台logger保存在cLogger属性上
self::$cLogger = $cLogger;
}
Application的初始化:
protected function init(): void
{
// Init system path aliases
// 设置基础路径(项目根目录)
$this->findBasePath();
// 设置并打印@base@app@config@runtime的路径别名
$this->setSystemAlias();
// 初始化EnvProcessor、ConfigProcessor、AnnotationProcessor
// BeanProcessor、EventProcessor、ConsoleProcessor
// 此6个处理器内容太多且只是初始化 后续章节实际调用时将说明
$processors = $this->processors();
// 初始化当前应用的处理器
$this->processor = new ApplicationProcessor($this);
// 将前面初始化的处理器交给当前应用处理器统一管理调度
$this->processor->addFirstProcessor(...$processors);
}
总结:
Application初始化顺序:
1.检查运行时环境.
2.触发初始化前事件.
3.初始化控制台logger.
4.初始化应用.
5.触发初始化后事件.