heyperf 是php 的一款协程框架, 我们在安装好 hyperf 之后, 在命令行使用
php bin/hyperf.php start 就可以将它启动, 那么这行命令到底做了什么工作,本人分析了一下源码, 大至看懂了一些, 这里做一下笔记
从入口进入看一下代码 也就是 hyperf.php
ini_set('display_errors', 'on');
ini_set('display_startup_errors', 'on');
ini_set('memory_limit', '1G');
error_reporting(E_ALL);
! defined('BASE_PATH') && define('BASE_PATH', dirname(__DIR__, 1));
! defined('SWOOLE_HOOK_FLAGS') && define('SWOOLE_HOOK_FLAGS', SWOOLE_HOOK_ALL);
require BASE_PATH . '/vendor/autoload.php';
(function () {
Hyperf\Di\ClassLoader::init();
$container = require BASE_PATH . '/config/container.php';
$application = $container->get(Hyperf\Contract\ApplicationInterface::class);
$application->run();
})();
从上现有代码中 三段代码中, 我们可以看到 第一段 定义一些常量, 修改一些php.ini中的配置,这个不用多说 第二段 composer 引入autoload.php , 这个也不用多说 第三段, 我们先看一下, 是一个匿名函数, 并且后面加了一个小括号, 说明就是一个立即执行的函数, 不懂为什么要这样写, 但是其作用就是, 执行了那段函数体中的代码 第一行 Hyperf\Di\ClassLoader::init(); 它的作用就是 psr-4 中的 autoload的一通加载, 反正就是自动加载了很多类 第二行 $container = require BASE_PATH . ‘/config/container.php’; 引入了 一个文件, 我们进入这个文件
$container = new Container((new DefinitionSourceFactory(true))());
if (! $container instanceof \Psr\Container\ContainerInterface) {
throw new RuntimeException('The dependency injection container is invalid.');
}
return ApplicationContext::setContainer($container);
这一行代码 $container = new Container((new DefinitionSourceFactory(true))()); 仔细看一下参数, (new classname())() 这种写法, 其实就是执行了 类中的 __invoke() 方法, 那么我们再进入 DefinitionSourceFactory 类中, 查看一下 __invoke()方法
class DefinitionSourceFactory
{
protected $enableCache = false;
protected $baseUri;
public function __construct(bool $enableCache = false)
{
$this->enableCache = $enableCache;
if (! defined('BASE_PATH')) {
throw new Exception('BASE_PATH is not defined.');
}
$this->baseUri = BASE_PATH;
}
public function __invoke()
{
$configDir = $this->baseUri . '/config';
$configFromProviders = [];
if (class_exists(ProviderConfig::class)) {
$configFromProviders = ProviderConfig::load();
}
$serverDependencies = $configFromProviders['dependencies'] ?? [];
if (file_exists($configDir . '/autoload/dependencies.php')) {
$definitions = include $configDir . '/autoload/dependencies.php';
$serverDependencies = array_replace($serverDependencies, $definitions ?? []);
}
return new DefinitionSource($serverDependencies);
}
}
在 __invoke()方法中, class_exists(ProviderConfig::class) 这个判断返回的是 true, 所以会执行 $configFromProviders = ProviderConfig::load();, 我们进入 load() 方法,
public static function load(): array
{
if (! static::$providerConfigs) {
$providers = Composer::getMergedExtra('hyperf')['config'] ?? [];
var_dump($providers);
exit;
static::$providerConfigs = static::loadProviders($providers);
}
return static::$providerConfigs;
}
因为有点看不懂 Composer::getMergedExtra(‘hyperf’)[‘config’] ?? []; 是在做什么, 所以我把 $providers 打印出来看了一下, 发现是我们安装的所有 插件的 ProviderConfig.php的文件的一个数组 如图 我们随便打开一个 ConfigProvider 看一下, 发现其格式大至是一样的
Hyperf\Framework\ConfigProvider Hyperf\Framework\ConfigProvider
基本上所有的 providerCofnig.php都是这一样的格式
再看一下 static::
p
r
o
v
i
d
e
r
C
o
n
f
i
g
s
=
s
t
a
t
i
c
:
:
l
o
a
d
P
r
o
v
i
d
e
r
s
(
providerConfigs = static::loadProviders(
providerConfigs=static::loadProviders(providers); 这一行代码 中的 loadProviders($providers);
protected static function loadProviders(array $providers): array
{
$providerConfigs = [];
foreach ($providers as $provider) {
if (is_string($provider) && class_exists($provider) && method_exists($provider, '__invoke')) {
$providerConfigs[] = (new $provider())();
}
}
return static::merge(...$providerConfigs);
}
可以看到, 它把所有的 ProviderConfig.php 文件都循环了一遍, 并且做了判断, 如果 数组中的这个类存在, 并且有 __invoke() 方法,就执行invoke(), 把返回后的数组再合并,所以, 我们可以想象返回的数组中有很多的,类似这样的记录
回到我们看到的 $configFromProviders = ProviderConfig::load(); 这个方法, 我们把 $configFormProviders打印出来看一下 太长了不能截图 复制下来就是下面的这个, 里面有 dependecies annotations listeners commands 等等
array(6) {
["dependencies"]=>
array(21) {
["Psr\SimpleCache\CacheInterface"]=>
string(18) "Hyperf\Cache\Cache"
["Hyperf\Contract\ConfigInterface"]=>
string(27) "Hyperf\Config\ConfigFactory"
["Hyperf\DbConnection\Pool\PoolFactory"]=>
string(36) "Hyperf\DbConnection\Pool\PoolFactory"
["Hyperf\Database\Connectors\ConnectionFactory"]=>
string(44) "Hyperf\Database\Connectors\ConnectionFactory"
["Hyperf\Database\ConnectionResolverInterface"]=>
string(38) "Hyperf\DbConnection\ConnectionResolver"
["db.connector.mysql"]=>
string(41) "Hyperf\Database\Connectors\MySqlConnector"
["Hyperf\Database\Migrations\MigrationRepositoryInterface"]=>
string(54) "Hyperf\DbConnection\DatabaseMigrationRepositoryFactory"
["Hyperf\Di\MethodDefinitionCollectorInterface"]=>
string(35) "Hyperf\Di\MethodDefinitionCollector"
["Hyperf\Di\ClosureDefinitionCollectorInterface"]=>
string(36) "Hyperf\Di\ClosureDefinitionCollector"
["Psr\EventDispatcher\ListenerProviderInterface"]=>
string(36) "Hyperf\Event\ListenerProviderFactory"
["Psr\EventDispatcher\EventDispatcherInterface"]=>
string(35) "Hyperf\Event\EventDispatcherFactory"
["Hyperf\ExceptionHandler\Formatter\FormatterInterface"]=>
string(50) "Hyperf\ExceptionHandler\Formatter\DefaultFormatter"
["Hyperf\Contract\ApplicationInterface"]=>
string(35) "Hyperf\Framework\ApplicationFactory"
["Hyperf\Contract\StdoutLoggerInterface"]=>
string(36) "Hyperf\Framework\Logger\StdoutLogger"
["Hyperf\HttpMessage\Server\RequestParserInterface"]=>
string(40) "Hyperf\HttpMessage\Server\Request\Parser"
["Hyperf\HttpServer\Contract\RequestInterface"]=>
string(25) "Hyperf\HttpServer\Request"
["Psr\Http\Message\ServerRequestInterface"]=>
string(25) "Hyperf\HttpServer\Request"
["Hyperf\HttpServer\Contract\ResponseInterface"]=>
string(26) "Hyperf\HttpServer\Response"
["Swoole\Server"]=>
string(33) "Hyperf\Server\SwooleServerFactory"
["Symfony\Component\Serializer\Serializer"]=>
string(41) "Hyperf\Utils\Serializer\SerializerFactory"
["Hyperf\Contract\NormalizerInterface"]=>
string(40) "Hyperf\Utils\Serializer\SimpleNormalizer"
}
["listeners"]=>
array(12) {
[0]=>
string(36) "Hyperf\Cache\Listener\DeleteListener"
[1]=>
string(54) "Hyperf\Config\Listener\RegisterPropertyHandlerListener"
[2]=>
string(63) "Hyperf\DbConnection\Listener\RegisterConnectionResolverListener"
[3]=>
string(57) "Hyperf\ExceptionHandler\Listener\ExceptionHandlerListener"
[4]=>
string(48) "Hyperf\ModelListener\Listener\ModelEventListener"
["Hyperf\ModelListener\Listener\ModelHookEventListener"]=>
int(99)
[5]=>
string(43) "Hyperf\Process\Listener\BootProcessListener"
[6]=>
string(54) "Hyperf\Process\Listener\LogAfterProcessStoppedListener"
[7]=>
string(53) "Hyperf\Process\Listener\LogBeforeProcessStartListener"
[8]=>
string(46) "Hyperf\Server\Listener\StoreServerNameListener"
[9]=>
string(47) "Hyperf\Server\Listener\AfterWorkerStartListener"
[10]=>
string(47) "Hyperf\Server\Listener\InitProcessTitleListener"
}
["annotations"]=>
array(2) {
["scan"]=>
array(2) {
["paths"]=>
array(18) {
[0]=>
string(46) "/var/www/hyperf/hyperf/vendor/hyperf/cache/src"
[1]=>
string(47) "/var/www/hyperf/hyperf/vendor/hyperf/config/src"
[2]=>
string(54) "/var/www/hyperf/hyperf/vendor/hyperf/db-connection/src"
[3]=>
string(43) "/var/www/hyperf/hyperf/vendor/hyperf/di/src"
[4]=>
string(51) "/var/www/hyperf/hyperf/vendor/hyperf/dispatcher/src"
[5]=>
string(46) "/var/www/hyperf/hyperf/vendor/hyperf/event/src"
[6]=>
string(58) "/var/www/hyperf/hyperf/vendor/hyperf/exception-handler/src"
[7]=>
string(50) "/var/www/hyperf/hyperf/vendor/hyperf/framework/src"
[8]=>
string(47) "/var/www/hyperf/hyperf/vendor/hyperf/guzzle/src"
[9]=>
string(52) "/var/www/hyperf/hyperf/vendor/hyperf/http-server/src"
[10]=>
string(47) "/var/www/hyperf/hyperf/vendor/hyperf/logger/src"
[11]=>
string(47) "/var/www/hyperf/hyperf/vendor/hyperf/memory/src"
[12]=>
string(55) "/var/www/hyperf/hyperf/vendor/hyperf/model-listener/src"
[13]=>
string(45) "/var/www/hyperf/hyperf/vendor/hyperf/pool/src"
[14]=>
string(48) "/var/www/hyperf/hyperf/vendor/hyperf/process/src"
[15]=>
string(47) "/var/www/hyperf/hyperf/vendor/hyperf/server/src"
[16]=>
string(46) "/var/www/hyperf/hyperf/vendor/hyperf/utils/src"
[17]=>
string(48) "/var/www/hyperf/hyperf/vendor/hyperf/devtool/src"
}
["collectors"]=>
array(4) {
[0]=>
string(35) "Hyperf\Cache\CacheListenerCollector"
[1]=>
string(40) "Hyperf\Di\Annotation\AnnotationCollector"
[2]=>
string(36) "Hyperf\Di\Annotation\AspectCollector"
[3]=>
string(48) "Hyperf\ModelListener\Collector\ListenerCollector"
}
}
["ignore_annotations"]=>
array(1) {
[0]=>
string(5) "mixin"
}
}
["publish"]=>
array(6) {
[0]=>
array(4) {
["id"]=>
string(6) "config"
["description"]=>
string(21) "The config for cache."
["source"]=>
string(67) "/var/www/hyperf/hyperf/vendor/hyperf/cache/src/../publish/cache.php"
["destination"]=>
string(48) "/var/www/hyperf/hyperf/config/autoload/cache.php"
}
[1]=>
array(4) {
["id"]=>
string(6) "config"
["description"]=>
string(24) "The config for database."
["source"]=>
string(79) "/var/www/hyperf/hyperf/vendor/hyperf/db-connection/src/../publish/databases.php"
["destination"]=>
string(52) "/var/www/hyperf/hyperf/config/autoload/databases.php"
}
[2]=>
array(4) {
["id"]=>
string(14) "query-listener"
["description"]=>
string(39) "The listener of database to record log."
["source"]=>
string(93) "/var/www/hyperf/hyperf/vendor/hyperf/db-connection/src/../publish/DbQueryExecutedListener.php"
["destination"]=>
string(63) "/var/www/hyperf/hyperf/app/Listener/DbQueryExecutedListener.php"
}
[3]=>
array(4) {
["id"]=>
string(6) "config"
["description"]=>
string(22) "The config for logger."
["source"]=>
string(69) "/var/www/hyperf/hyperf/vendor/hyperf/logger/src/../publish/logger.php"
["destination"]=>
string(49) "/var/www/hyperf/hyperf/config/autoload/logger.php"
}
[4]=>
array(4) {
["id"]=>
string(6) "config"
["description"]=>
string(22) "The config for server."
["source"]=>
string(69) "/var/www/hyperf/hyperf/vendor/hyperf/server/src/../publish/server.php"
["destination"]=>
string(49) "/var/www/hyperf/hyperf/config/autoload/server.php"
}
[5]=>
array(4) {
["id"]=>
string(6) "config"
["description"]=>
string(23) "The config for devtool."
["source"]=>
string(71) "/var/www/hyperf/hyperf/vendor/hyperf/devtool/src/../publish/devtool.php"
["destination"]=>
string(50) "/var/www/hyperf/hyperf/config/autoload/devtool.php"
}
}
["aspects"]=>
array(2) {
[0]=>
string(36) "Hyperf\Config\Annotation\ValueAspect"
[1]=>
string(33) "Hyperf\Di\Annotation\InjectAspect"
}
["commands"]=>
array(15) {
[0]=>
string(37) "Hyperf\Database\Commands\ModelCommand"
[1]=>
string(53) "Hyperf\Database\Commands\Migrations\GenMigrateCommand"
[2]=>
string(50) "Hyperf\Database\Commands\Migrations\InstallCommand"
[3]=>
string(50) "Hyperf\Database\Commands\Migrations\MigrateCommand"
[4]=>
string(48) "Hyperf\Database\Commands\Migrations\FreshCommand"
[5]=>
string(50) "Hyperf\Database\Commands\Migrations\RefreshCommand"
[6]=>
string(48) "Hyperf\Database\Commands\Migrations\ResetCommand"
[7]=>
string(51) "Hyperf\Database\Commands\Migrations\RollbackCommand"
[8]=>
string(49) "Hyperf\Database\Commands\Migrations\StatusCommand"
[9]=>
string(49) "Hyperf\Database\Commands\Seeders\GenSeederCommand"
[10]=>
string(44) "Hyperf\Database\Commands\Seeders\SeedCommand"
[11]=>
string(33) "Hyperf\Server\Command\StartServer"
[12]=>
string(38) "Hyperf\Devtool\Describe\AspectsCommand"
[13]=>
string(40) "Hyperf\Devtool\Describe\ListenersCommand"
[14]=>
string(37) "Hyperf\Devtool\Describe\RoutesCommand"
}
}
继续往下走代码 得到了 configFormProviders 是上面的一堆数组, 它又得我们自定义的配置进行合并, 最终得到 一个 $serverDependencies 的数组做为参数 我们把 $serverDependencies 打印出来看一下
[“Psr\SimpleCache\CacheInterface”]=>string(18) “Hyperf\Cache\Cache” [“Hyperf\Contract\ConfigInterface”]=>string(27) “Hyperf\Config\ConfigFactory” 可以看到是这样子的格式的键值对, 这其实就是 container 容器中的键值对,
重点, 说白了, 也就是说 当我们获得容器中的对象时, 它的键就是上图中的键
如:我们想得到一个 Hyperf\Cache\Cache 的实例, 我们就要使用 $container->get(Psr\SimpleCache\CacheInterface::class),得到的对象就是容器中的 Hyperf\Cache\Cache , 这一点很重要, hyperf中很多都是使用这种获取的
继续回到上层的方法如图 我们对参数研究完毕子, 现在看一下 Container的 构造函数都干了些什么
前两句定义了两个属性, 在红箭头处 相当于是给 这个 容器中加入了 指向自己的键, 也就是说这三个键都指向了自已
所以当我们使用 $container->get(Psr\Container\ContainerInterface::class) 或者 $container->get(Hyperf\Contract\ContainerInterface::class) 又或者
c
o
n
t
a
i
n
e
r
?
>
g
e
t
(
g
e
t
c
l
a
s
s
(
container->get(get_class(
container?>get(getc?lass(container))得到的都是container容器对象这些是题外话, 不重要, 可以不看
继续往下走, ApplicationContext::setContainer($container); 还是返回了容器对象 返回到上一层代码中
上面的代码得到了 $container , 然后从容器中得到 键名为 Hyperf\Contract\ApplicationInterface::class 的对象, 那么这里一个什么对象了, 我们应该在 ProviderConfig.php文件中的 dependencies 中去找 最终在这里找到了 也就是说它实际上是一个 ApplicationFactory::class的一个对象, 同样的了我们要看 ApplicationFactory::class的 __invoke() 方法
class ApplicationFactory
{
public function __invoke(ContainerInterface $container)
{
if ($container->has(EventDispatcherInterface::class)) {
$eventDispatcher = $container->get(EventDispatcherInterface::class);
$eventDispatcher->dispatch(new BootApplication());
}
$config = $container->get(ConfigInterface::class);
$commands = $config->get('commands', []);
$annotationCommands = [];
if (class_exists(AnnotationCollector::class) && class_exists(Command::class)) {
$annotationCommands = AnnotationCollector::getClassesByAnnotation(Command::class);
$annotationCommands = array_keys($annotationCommands);
}
$commands = array_unique(array_merge($commands, $annotationCommands));
$application = new Application();
if (isset($eventDispatcher) && class_exists(SymfonyEventDispatcher::class)) {
$application->setDispatcher(new SymfonyEventDispatcher($eventDispatcher));
}
foreach ($commands as $command) {
$application->add($container->get($command));
}
return $application;
}
}
从上面的代码中我们可以看到, 这其实是 Symfony\Component\Console\Application; 也就是一个命令行的对象, 我们在代码中 把$commands 数组找印出来 可以看到, 在这段代码中注册了这么多的 命令行代码类, 其中我们开启用的 /bin/hyperf.php start,所以我们看一下 上面的 startServer 类, 就知道,hyperf是怎么启动的了
StartServer.php
<?php
declare(strict_types=1);
namespace Hyperf\Server\Command;
use Hyperf\Contract\ConfigInterface;
use Hyperf\Contract\StdoutLoggerInterface;
use Hyperf\Engine\Coroutine;
use Hyperf\Server\ServerFactory;
use InvalidArgumentException;
use Psr\Container\ContainerInterface;
use Psr\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class StartServer extends Command
{
private $container;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
parent::__construct('start');
$this->setDescription('Start hyperf servers.');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$this->checkEnvironment($output);
$serverFactory = $this->container->get(ServerFactory::class)
->setEventDispatcher($this->container->get(EventDispatcherInterface::class))
->setLogger($this->container->get(StdoutLoggerInterface::class));
$serverConfig = $this->container->get(ConfigInterface::class)->get('server', []);
if (! $serverConfig) {
throw new InvalidArgumentException('At least one server should be defined.');
}
$serverFactory->configure($serverConfig);
Coroutine::set(['hook_flags' => swoole_hook_flags()]);
$serverFactory->start();
return 0;
}
private function checkEnvironment(OutputInterface $output)
{
if (! extension_loaded('swoole')) {
return;
}
$useShortname = ini_get_all('swoole')['swoole.use_shortname']['local_value'];
$useShortname = strtolower(trim(str_replace('0', '', $useShortname)));
if (! in_array($useShortname, ['', 'off', 'false'], true)) {
$output->writeln('<error>ERROR</error> Swoole short name have to disable before start server, please set swoole.use_shortname = off into your php.ini.');
exit(SIGTERM);
}
}
}
这个类是继承了 Symfony\Component\Console Command的, 所以我们关建看 execute() 方法 而方法中, 我们关键看 $serverFactory->start(); 进入 $serverFactory 中, 我们就可以看到一个 getServer方法 我们把 $serverName 打印出来 最终我们就看的是 Hyperf\Server\Server 的 start()方法, 启动的服务 启动类就是它了 看一下代码,就可以看个八九不离十的
<?php
declare(strict_types=1);
namespace Hyperf\Server;
use Hyperf\Contract\MiddlewareInitializerInterface;
use Hyperf\Framework\Bootstrap;
use Hyperf\Framework\Event\BeforeMainServerStart;
use Hyperf\Framework\Event\BeforeServerStart;
use Hyperf\Server\Exception\RuntimeException;
use Psr\Container\ContainerInterface;
use Psr\EventDispatcher\EventDispatcherInterface;
use Psr\Log\LoggerInterface;
use Swoole\Http\Server as SwooleHttpServer;
use Swoole\Server as SwooleServer;
use Swoole\WebSocket\Server as SwooleWebSocketServer;
class Server implements ServerInterface
{
protected $enableHttpServer = false;
protected $enableWebsocketServer = false;
protected $server;
protected $onRequestCallbacks = [];
protected $logger;
protected $container;
protected $eventDispatcher;
public function __construct(ContainerInterface $container, LoggerInterface $logger, EventDispatcherInterface $dispatcher)
{
$this->container = $container;
$this->logger = $logger;
$this->eventDispatcher = $dispatcher;
}
public function init(ServerConfig $config): ServerInterface
{
$this->initServers($config);
return $this;
}
public function start()
{
$this->server->start();
}
public function getServer()
{
return $this->server;
}
protected function initServers(ServerConfig $config)
{
$servers = $this->sortServers($config->getServers());
foreach ($servers as $server) {
$name = $server->getName();
$type = $server->getType();
$host = $server->getHost();
$port = $server->getPort();
$sockType = $server->getSockType();
$callbacks = $server->getCallbacks();
if (! $this->server instanceof SwooleServer) {
$this->server = $this->makeServer($type, $host, $port, $config->getMode(), $sockType);
$callbacks = array_replace($this->defaultCallbacks(), $config->getCallbacks(), $callbacks);
$this->registerSwooleEvents($this->server, $callbacks, $name);
$this->server->set(array_replace($config->getSettings(), $server->getSettings()));
ServerManager::add($name, [$type, current($this->server->ports)]);
if (class_exists(BeforeMainServerStart::class)) {
$this->eventDispatcher->dispatch(new BeforeMainServerStart($this->server, $config->toArray()));
}
} else {
$slaveServer = $this->server->addlistener($host, $port, $sockType);
if (! $slaveServer) {
throw new \RuntimeException("Failed to listen server port [{$host}:{$port}]");
}
$server->getSettings() && $slaveServer->set(array_replace($config->getSettings(), $server->getSettings()));
$this->registerSwooleEvents($slaveServer, $callbacks, $name);
ServerManager::add($name, [$type, $slaveServer]);
}
if (isset($callbacks[Event::ON_BEFORE_START])) {
[$class, $method] = $callbacks[Event::ON_BEFORE_START];
if ($this->container->has($class)) {
$this->container->get($class)->{$method}();
}
}
if (class_exists(BeforeServerStart::class)) {
$this->eventDispatcher->dispatch(new BeforeServerStart($name));
}
}
}
protected function sortServers(array $servers)
{
$sortServers = [];
foreach ($servers as $server) {
switch ($server->getType() ?? 0) {
case ServerInterface::SERVER_HTTP:
$this->enableHttpServer = true;
if (! $this->enableWebsocketServer) {
array_unshift($sortServers, $server);
} else {
$sortServers[] = $server;
}
break;
case ServerInterface::SERVER_WEBSOCKET:
$this->enableWebsocketServer = true;
array_unshift($sortServers, $server);
break;
default:
$sortServers[] = $server;
break;
}
}
return $sortServers;
}
protected function makeServer(int $type, string $host, int $port, int $mode, int $sockType)
{
switch ($type) {
case ServerInterface::SERVER_HTTP:
return new SwooleHttpServer($host, $port, $mode, $sockType);
case ServerInterface::SERVER_WEBSOCKET:
return new SwooleWebSocketServer($host, $port, $mode, $sockType);
case ServerInterface::SERVER_BASE:
return new SwooleServer($host, $port, $mode, $sockType);
}
throw new RuntimeException('Server type is invalid.');
}
protected function registerSwooleEvents($server, array $events, string $serverName): void
{
foreach ($events as $event => $callback) {
if (! Event::isSwooleEvent($event)) {
continue;
}
if (is_array($callback)) {
[$className, $method] = $callback;
if (array_key_exists($className . $method, $this->onRequestCallbacks)) {
$this->logger->warning(sprintf('%s will be replaced by %s. Each server should have its own onRequest callback. Please check your configs.', $this->onRequestCallbacks[$className . $method], $serverName));
}
$this->onRequestCallbacks[$className . $method] = $serverName;
$class = $this->container->get($className);
if (method_exists($class, 'setServerName')) {
$class->setServerName($serverName);
}
if ($class instanceof MiddlewareInitializerInterface) {
$class->initCoreMiddleware($serverName);
}
$callback = [$class, $method];
}
$server->on($event, $callback);
}
}
protected function defaultCallbacks()
{
$hasCallback = class_exists(Bootstrap\StartCallback::class)
&& class_exists(Bootstrap\ManagerStartCallback::class)
&& class_exists(Bootstrap\WorkerStartCallback::class);
if ($hasCallback) {
$callbacks = [
Event::ON_MANAGER_START => [Bootstrap\ManagerStartCallback::class, 'onManagerStart'],
Event::ON_WORKER_START => [Bootstrap\WorkerStartCallback::class, 'onWorkerStart'],
Event::ON_WORKER_STOP => [Bootstrap\WorkerStopCallback::class, 'onWorkerStop'],
Event::ON_WORKER_EXIT => [Bootstrap\WorkerExitCallback::class, 'onWorkerExit'],
];
if ($this->server->mode === SWOOLE_BASE) {
return $callbacks;
}
return array_merge([
Event::ON_START => [Bootstrap\StartCallback::class, 'onStart'],
], $callbacks);
}
return [
Event::ON_WORKER_START => function (SwooleServer $server, int $workerId) {
printf('Worker %d started.' . PHP_EOL, $workerId);
},
];
}
}
以上就是 hyperf的启动源码分析, 功夫不好, 有些地方看不太懂, 就用了 var_dump 大法, 见笑, 总算还可以看到头绪,欣慰
|