hyperf console 执行

一、原理描述

hyperf中,不难发现比如自定义控制器中获取参数,hyperf.php中容器获取,传入的都是接口,而不是实体类。

这是因为框架中的配置文件有设置对应抽象类的子类,框架加载的时候将其作为数组,使用的时候通过数组对应子类。

实现这个功能就需要composer autoload 代理,即生成的composer.lock文件再处理。但是需要其余对应的composer拉取的程序在composer.json中设置对应数据。

例如

//vendor\hyperf\http-server\composer.json
"extra": {"branch-alias": {"dev-master": "2.2-dev"},"hyperf": {"config": "Hyperf\\HttpServer\\ConfigProvider"}}
//vendor\hyperf\db-connection\composer.json"extra": {"branch-alias": {"dev-master": "2.2-dev"},"hyperf": {"config": "Hyperf\\DbConnection\\ConfigProvider"}}
#vendor/hyperf/http-server/src/ConfigProvider.php
namespace Hyperf\HttpServer;use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Contract\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;class ConfigProvider
{public function __invoke(): array{return ['dependencies' => [RequestInterface::class => Request::class,ServerRequestInterface::class => Request::class,ResponseInterface::class => Response::class,],'annotations' => ['scan' => ['paths' => [__DIR__,],],],];}
}#vendor\hyperf\db-connection\src\ConfigProvider.php
namespace Hyperf\DbConnection;use Hyperf\Database\Commands\Migrations\FreshCommand;
use Hyperf\Database\Commands\Migrations\GenMigrateCommand;
use Hyperf\Database\Commands\Migrations\InstallCommand;
use Hyperf\Database\Commands\Migrations\MigrateCommand;
use Hyperf\Database\Commands\Migrations\RefreshCommand;
use Hyperf\Database\Commands\Migrations\ResetCommand;
use Hyperf\Database\Commands\Migrations\RollbackCommand;
use Hyperf\Database\Commands\Migrations\StatusCommand;
use Hyperf\Database\Commands\ModelCommand;
use Hyperf\Database\Commands\Seeders\GenSeederCommand;
use Hyperf\Database\Commands\Seeders\SeedCommand;
use Hyperf\Database\ConnectionResolverInterface;
use Hyperf\Database\Connectors\ConnectionFactory;
use Hyperf\Database\Connectors\MySqlConnector;
use Hyperf\Database\Migrations\MigrationRepositoryInterface;
use Hyperf\DbConnection\Listener\RegisterConnectionResolverListener;
use Hyperf\DbConnection\Pool\PoolFactory;class ConfigProvider
{public function __invoke(): array{return ['dependencies' => [PoolFactory::class => PoolFactory::class,ConnectionFactory::class => ConnectionFactory::class,ConnectionResolverInterface::class => ConnectionResolver::class,'db.connector.mysql' => MySqlConnector::class,MigrationRepositoryInterface::class => DatabaseMigrationRepositoryFactory::class,],'commands' => [ModelCommand::class,GenMigrateCommand::class,InstallCommand::class,MigrateCommand::class,FreshCommand::class,RefreshCommand::class,ResetCommand::class,RollbackCommand::class,StatusCommand::class,GenSeederCommand::class,SeedCommand::class,],'listeners' => [RegisterConnectionResolverListener::class,],'annotations' => ['scan' => ['paths' => [__DIR__,],],],'publish' => [['id' => 'config','description' => 'The config for database.','source' => __DIR__ . '/../publish/databases.php','destination' => BASE_PATH . '/config/autoload/databases.php',],['id' => 'query-listener','description' => 'The listener of database to record log.','source' => __DIR__ . '/../publish/DbQueryExecutedListener.php','destination' => BASE_PATH . '/app/Listener/DbQueryExecutedListener.php',],],];}
}

以bin/hyperf.php为例,加载autoload.php文件,执行Hyperf\Di\ClassLoader::init()设置,执行

$application->run();输出命令。

1.1 Hyperf\Di\ClassLoader::init()

Hyperf\Di\ClassLoader::init() 加载配置文件、composer.lock,并合并数据。

主要使用Composer::getMergedExtra('hyperf')['config'],就是composer.lock中extra中的hyperf中config值。

根据config中的值,调用其__invoke()获取数组,并设置。

在上述过程中,涉及ProviderConfig::load();运行,会对ProviderConfig::$providerConfigs数据进行初始化。

ProviderConfig::load()获取的值中包括每个composer拉取的程序中ConfigProvider.php文件中的内容,当然也就包括commands。

ProviderConfig::load()在之后也会被使用。

ClassLoader::init()会调用其构造函数,打印ClassLoader构造中的$config = ScanConfig::instance($configDir);结果,可以看到类内的成员变量包括cacheable、configDir、paths、collectors、ignoreAnnotations、globalImports、dependencies、classMap。

就bin/hyperf.php而言,此时并没有使用配置中的commands数据。

1.2 /config/container.php

hyperf.php中随后加载/config/container.php。

container.php中通过$container = new Container((new DefinitionSourceFactory(true))());,调用DefinitionSourceFactory的构造和__invoke()方法。

DefinitionSourceFactory::__invoke()中通过ProviderConfig::load();加载配置,获取配置中的dependencies数组,最后返回key和object对应的数组。

container.php文件最后返回 Hyperf\Di\Container类,其构造参数的为DefinitionSourceFactory::__invoke()返回的数组。

Hyperf\Di\Container构造方法中会设置$this->definitionSource和$this->resolvedEntries。

1.3 $container->get()

$application对象通过$application = $container->get(Hyperf\Contract\ApplicationInterface::class);获取。调用$container->get()会先判断Container::resolvedEntries是否有数据,有则返回,否则使用Container::make()使用Container::definitionSource创建数据。最后返回对应的实体类。

即为,$application = $container->get(Hyperf\Contract\ApplicationInterface::class);返回ApplicationFactory类,ApplicationFactory构造最后返回Symfony\Component\Console\Application类。

Hyperf\Contract\ApplicationInterface::__invoke()会先执行。其中运行Application::__construct(),设置默认值,比如默认命令为“list”。__invoke()还会将commands数据添加到Symfony\Component\Console\Application中。

1.4 Application::run()

调用 $application->run();,就是调用Symfony\Component\Console\Application::run()。

对于配置文件中commands的处理、console的使用也是在Application::run()方法中。

Application::run()调用Application::doRun()。

doRun()中执行默认的命令“list”,运行Symfony\Component\Console\Command\ListCommand::execute(),其中运行DescriptorHelper::__construct()。

ListCommand::execute()通过DescriptorHelper::describe()运行TextDescriptor(默认)的父类Descriptor::describe()。

Descriptor::describe()中通过其子类实现的describeApplication()方法,获取项目中的commands(配置中的commands),这里即为TextDescriptor::describeApplication()。

TextDescriptor::describeApplication()中通过调用 ConsoleOutput->write()输出内容。

每个命令的execute()方法通过其父类Symfony\Component\Console\Command:run()调用。

dorun()中调用doRunCommand(),这其中会调用Command:run()。

二、原理总结

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/583924.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

零基础学Java第二天

复习回顾: 1.dos命令 dir 显示当前文件夹下面的所有的文件和文件夹 cd 切换目录的 mkdir 创建文件夹的 rd 删除文件夹的 del 删除文件 D: 切换盘符 cls 清屏 2.书写Java代码换行打印《静夜诗》这首古诗 class Demo1 { …

深入理解 C# 中的字符串比较:String.CompareTo vs String.Equals

深入理解 C# 中的字符串比较:String.CompareTo vs String.Equals 在处理字符串时,了解如何正确比较它们对于编写清晰、有效和可靠的 C# 程序至关重要。本文将深入探讨 C# 中的两个常用字符串比较方法:String.CompareTo 和 String.Equals&…

Mybatis行为配置之Ⅲ—其他行为配置项说明

专栏精选 引入Mybatis Mybatis的快速入门 Mybatis的增删改查扩展功能说明 mapper映射的参数和结果 Mybatis复杂类型的结果映射 Mybatis基于注解的结果映射 Mybatis枚举类型处理和类型处理器 再谈动态SQL Mybatis配置入门 Mybatis行为配置之Ⅰ—缓存 Mybatis行为配置…

电子工程师如何接私活赚外快?

对电子工程师来说,利用业余时间接私活是个很常见的技术,不仅可以赚取额外收入,也能提升巩固技术,可以说国内十个工程师,必有五个在接私活养家糊口,如果第一次接私活,该如何做? 很多工…

再升级|川石教育鸿蒙应用开发4.0教程发布

全新鸿蒙蓄势待发 HarmonyOS是一款面向未来的全场景分布式智慧操作系统。 对于消费者而言,HarmonyOS用一个统一的软件系统从根本上解决消费者面对大量智能终端体验割裂的问题,为消费者带来统一、便利、安全的智慧化全场景体验。 对于开发者而言&#xf…

十二:爬虫-Scrapy框架(上)

一:Scrapy介绍 1.Scrapy是什么? Scrapy 是用 Python 实现的一个为了爬取网站数据、提取结构性数据而编写的应用框架(异步爬虫框架) 通常我们可以很简单的通过 Scrapy 框架实现一个爬虫,抓取指定网站的内容或图片 Scrapy使用了Twisted异步网…

(切图笔记)layui表格单元格添加超链接 以及传参方法 亲测可用 附代码

layui在切图网日常的工作中常常用到,特别是它的layer弹窗,基本可以满足网站切图时候遇到的绝大多数弹窗的情况,参数比较丰富 灵活,是不可多得的网页插件之一,我见很多人说layui过时了,这是相比于vue正流行的…

Java8 - 更优雅的字符串连接(join)收集器 Collectors.joining

Java8中的字符串连接收集器 在JDK8中,可以采用函数式编程(使用 Collectors.joining 收集器)的方式对字符串进行更优雅的连接。 Collectors.joining 收集器 支持灵活的参数配置,可以指定字符串连接时的 分隔符,前缀 和…

Sentinel-3如何处理并下载LST数据-陆地表面温度”(Land Surface Temperature)

LST 通常指的是“陆地表面温度”(Land Surface Temperature)。陆地表面温度是指地球表面上陆地部分的温度,而不包括水体表面。LST 是遥感技术中一个重要的参数,可以通过卫星遥感等手段进行测量和监测。 陆地表面温度对于许多领域…

浅谈高并发以及三大利器:缓存、限流和降级

引言 高并发背景 互联网行业迅速发展,用户量剧增,系统面临巨大的并发请求压力。 软件系统有三个追求:高性能、高并发、高可用,俗称三高。三者既有区别也有联系,门门道道很多,全面讨论需要三天三夜&#…

人工智能_机器学习072_SVM支持向量机_人脸识别模型训练_训练时间过长解决办法_数据降维_LFW人脸数据建模与C参数选择---人工智能工作笔记0112

我们先来看一下之前的代码: import numpy as np 导入数学计算库 from sklearn. svm import SVC 导入支持向量机 线性分类器 import matplotlib.pyplot as plt 加载人脸图片以后,我们用pyplot把人脸图片数据展示一下 from sklearn.model_selection import train_test_split 人脸…

Unity之组件的生命周期

PS:第二天,依旧在摸鱼学unity 一、组件的概念 我本身是由Web后端转到了游戏后端,最近因为工作原因在学ET框架。学到了 ECS 编程模式开发(E —— Entity,C —— Component , S —— System)实体、…

【rosbag】rosbag命令--查看提取bag中的内容

1.查看消息 rosbag info --.bag topics是其中的话题内容,/imu中只写了包含imu的数据,但是imu是9轴的,到底磁力计信息是否包含在其中呢? 2.将bag中的某个话题转为txt 将file_name.bag文件中topic_name话题的消息转换到Txt_name.…

BIT-666 的 2023 年度总结

<<< 年度总结 >>> <<< 年度数据 >>> ◆ 发博情况 ◆ 学习成就 ◆ 代码提交 ◆ 博文表现 <<< 年度创作 >>> ◆ LLM - LLaMA2 <<< 年度风景 >>> ◆ 春 - 中关村软件园 - 百望山 ◆ 夏 - 乌兰…

Python开发一个电商平台历史价格查询软件

嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! python更多源码/资料/解答/教程等 点击此处跳转文末名片免费获取 环境介绍: python 3.8 pycharm 专业版 第三方模块使用 requests ——> 发送 HTTP 请求 execjs ——> 用来执行JavaScript代码 pyecharts ——> 生成…

视频美颜sdk是什么?美颜sdk贴纸技术详解

如今&#xff0c;贴纸技术作为视频美颜的一个创新分支&#xff0c;为用户提供了更加丰富多彩的互动体验。本文将深入探讨视频美颜SDK中的贴纸技术&#xff0c;揭示其技术原理、应用场景以及未来发展趋势。 一、贴纸技术的背后&#xff1a;图像处理与人脸识别 这一步骤是实现贴…

关于IDEA中Git版本回滚整理

Git分区理解 git的版本回滚本质上就是回滚不同的分区&#xff0c;所以咱们有必要简单了解一下git的分区。git在本地有三大分区&#xff1a;暂存区、工作区、版本库。 暂存区: add后的代码&#xff0c;绿色。 **工作区&#xff1a;**正在编写&#xff0c;还未add的部分&#…

【Vue】事件修饰符详解

✨ 专栏介绍 在当今Web开发领域中&#xff0c;构建交互性强、可复用且易于维护的用户界面是至关重要的。而Vue.js作为一款现代化且流行的JavaScript框架&#xff0c;正是为了满足这些需求而诞生。它采用了MVVM架构模式&#xff0c;并通过数据驱动和组件化的方式&#xff0c;使…

【SpringBoot篇】详解Bean的管理(获取bean,bean的作用域,第三方bean)

文章目录 &#x1f354;Bean的获取&#x1f384;注入IOC容器对象⭐代码实现&#x1f6f8;根据bean的名称获取&#x1f6f8;根据bean的类型获取&#x1f6f8;根据bean的名称和类型获取 &#x1f384;Bean的作用域⭐代码实现&#x1f388;注意 &#x1f384;第三方Bean⭐代码实现…

设计模式-对象池模式

设计模式专栏 模式介绍模式特点应用场景对象池模式和工厂模式的区别代码示例Java实现对象池模式Python实现对象池模式 对象池模式在spring中的应用 模式介绍 对象池模式是一种创建型设计模式&#xff0c;它将对象预先创建并初始化后放入一个池中&#xff0c;以供其他对象使用。…