laravel请求到响应的生命周期
请求到响应的核个执行过程,主要可以归纳为四个阶段,即程序启动准备阶段、请求实例化阶段、请求处理阶段、响应发送和程序终止阶段。
public\index.php中有这么一段代码
$app = require_once __DIR__.'/../bootstrap/app.php';
//app.php
<?php
//用来实现服务容器的实例化过程
$app = new Illuminate\Foundation\Application(
realpath(__DIR__.'/../')
); //下面代码向服务容器中绑定核心类服务,并返回核心类服务 $app->singleton(
Illuminate\Contracts\Http\Kernel::class,
App\Http\Kernel::class
); $app->singleton(
Illuminate\Contracts\Console\Kernel::class,
App\Console\Kernel::class
); $app->singleton(
Illuminate\Contracts\Debug\ExceptionHandler::class,
App\Exceptions\Handler::class
); return $app;
Illuminate\Foundation\Application
class Application extends Container implements ApplicationContract, HttpKernelInterface
public function __construct($basePath = null)
{
if ($basePath) {
//注册应用的基础路径
$this->setBasePath($basePath);
} //用来绑定基础服务,主要是绑定容器实例本身,是的其它对象可以很容易得到服务容器实例
$this->registerBaseBindings();
//注册基础服务提供者
$this->registerBaseServiceProviders();
//注册核心类别名和应用的基础路径
$this->registerCoreContainerAliases();
}
setBasePath
public function setBasePath($basePath)
{
$this->basePath = rtrim($basePath, '\/');
//在容器中绑定应用程序的基础路径
$this->bindPathsInContainer(); return $this;
}
registerBaseBindings
protected function registerBaseBindings()
{
static::setInstance($this); $this->instance('app', $this); $this->instance(Container::class, $this); $this->instance(PackageManifest::class, new PackageManifest(
new Filesystem, $this->basePath(), $this->getCachedPackagesPath()
));
} public function instance($abstract, $instance)
{
$this->removeAbstractAlias($abstract); $isBound = $this->bound($abstract); unset($this->aliases[$abstract]); // We'll check to determine if this type has been bound before, and if it has
// we will fire the rebound callbacks registered with the container and it
// can be updated with consuming classes that have gotten resolved here.
$this->instances[$abstract] = $instance; if ($isBound) {
$this->rebound($abstract);
} return $instance;
}
registerBaseServiceProviders
protected function registerBaseServiceProviders()
{
$this->register(new EventServiceProvider($this)); $this->register(new LogServiceProvider($this)); $this->register(new RoutingServiceProvider($this));
} public function register($provider, $options = [], $force = false)
{
//如果服务者已经存在 则获取这个实例对象
if (($registered = $this->getProvider($provider)) && ! $force) {
return $registered;
} //通过类名实例化一个服务提供者
if (is_string($provider)) {
$provider = $this->resolveProvider($provider);
}
//向服务容器中注册服务
if (method_exists($provider, 'register')) {
//每个服务提供者必须实现这个函数,用来填充服务器并提供服务
$provider->register();
}
//标识该服务提供者已经注册过了
$this->markAsRegistered($provider);
if ($this->booted) {
//启动规定的服务器供者 并且会调用服务提供者的boot函数
//boot这个函数服务提供者可以不用实现
$this->bootProvider($provider);
}
return $provider;
}
registerCoreContainerAliases :定义了整个框架的核心服务别名
public function registerCoreContainerAliases()
{
foreach ([
'app' => [\Illuminate\Foundation\Application::class, \Illuminate\Contracts\Container\Container::class, \Illuminate\Contracts\Foundation\Application::class, \Psr\Container\ContainerInterface::class],
'auth' => [\Illuminate\Auth\AuthManager::class, \Illuminate\Contracts\Auth\Factory::class],
'auth.driver' => [\Illuminate\Contracts\Auth\Guard::class],
'blade.compiler' => [\Illuminate\View\Compilers\BladeCompiler::class],
'cache' => [\Illuminate\Cache\CacheManager::class, \Illuminate\Contracts\Cache\Factory::class],
'cache.store' => [\Illuminate\Cache\Repository::class, \Illuminate\Contracts\Cache\Repository::class],
'config' => [\Illuminate\Config\Repository::class, \Illuminate\Contracts\Config\Repository::class],
'cookie' => [\Illuminate\Cookie\CookieJar::class, \Illuminate\Contracts\Cookie\Factory::class, \Illuminate\Contracts\Cookie\QueueingFactory::class],
'encrypter' => [\Illuminate\Encryption\Encrypter::class, \Illuminate\Contracts\Encryption\Encrypter::class],
'db' => [\Illuminate\Database\DatabaseManager::class],
'db.connection' => [\Illuminate\Database\Connection::class, \Illuminate\Database\ConnectionInterface::class],
'events' => [\Illuminate\Events\Dispatcher::class, \Illuminate\Contracts\Events\Dispatcher::class],
'files' => [\Illuminate\Filesystem\Filesystem::class],
'filesystem' => [\Illuminate\Filesystem\FilesystemManager::class, \Illuminate\Contracts\Filesystem\Factory::class],
'filesystem.disk' => [\Illuminate\Contracts\Filesystem\Filesystem::class],
'filesystem.cloud' => [\Illuminate\Contracts\Filesystem\Cloud::class],
'hash' => [\Illuminate\Contracts\Hashing\Hasher::class],
'translator' => [\Illuminate\Translation\Translator::class, \Illuminate\Contracts\Translation\Translator::class],
'log' => [\Illuminate\Log\Writer::class, \Illuminate\Contracts\Logging\Log::class, \Psr\Log\LoggerInterface::class],
'mailer' => [\Illuminate\Mail\Mailer::class, \Illuminate\Contracts\Mail\Mailer::class, \Illuminate\Contracts\Mail\MailQueue::class],
'auth.password' => [\Illuminate\Auth\Passwords\PasswordBrokerManager::class, \Illuminate\Contracts\Auth\PasswordBrokerFactory::class],
'auth.password.broker' => [\Illuminate\Auth\Passwords\PasswordBroker::class, \Illuminate\Contracts\Auth\PasswordBroker::class],
'queue' => [\Illuminate\Queue\QueueManager::class, \Illuminate\Contracts\Queue\Factory::class, \Illuminate\Contracts\Queue\Monitor::class],
'queue.connection' => [\Illuminate\Contracts\Queue\Queue::class],
'queue.failer' => [\Illuminate\Queue\Failed\FailedJobProviderInterface::class],
'redirect' => [\Illuminate\Routing\Redirector::class],
'redis' => [\Illuminate\Redis\RedisManager::class, \Illuminate\Contracts\Redis\Factory::class],
'request' => [\Illuminate\Http\Request::class, \Symfony\Component\HttpFoundation\Request::class],
'router' => [\Illuminate\Routing\Router::class, \Illuminate\Contracts\Routing\Registrar::class, \Illuminate\Contracts\Routing\BindingRegistrar::class],
'session' => [\Illuminate\Session\SessionManager::class],
'session.store' => [\Illuminate\Session\Store::class, \Illuminate\Contracts\Session\Session::class],
'url' => [\Illuminate\Routing\UrlGenerator::class, \Illuminate\Contracts\Routing\UrlGenerator::class],
'validator' => [\Illuminate\Validation\Factory::class, \Illuminate\Contracts\Validation\Factory::class],
'view' => [\Illuminate\View\Factory::class, \Illuminate\Contracts\View\Factory::class],
] as $key => $aliases) {
foreach ($aliases as $alias) {
$this->alias($key, $alias);
}
}
}
至此应用程序的准备工作已经完成
接下来我们再来看看index.php
/**
* 主要实现了服务容器的实例化和基本注册
*包括服务容器本身的注册,基础服务提供者注册,核心类别名注册和基本路径注册
*
*/
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class); //处理请求
$response = $kernel->handle(
//请求实例的创建
$request = Illuminate\Http\Request::capture()
);
namespace Illuminate\Foundation\Http\Kernel
/**
* Handle an incoming HTTP request.
*处理一个http请求
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function handle($request)
{
try {
//在请求过程中会添加CSRF保护,服务端会发送一个csrf令牌给客户端(cookie)
$request->enableHttpMethodParameterOverride();
//请求处理,通过路由传输请求实例
$response = $this->sendRequestThroughRouter($request);
} catch (Exception $e) {
$this->reportException($e); $response = $this->renderException($request, $e);
} catch (Throwable $e) {
$this->reportException($e = new FatalThrowableError($e)); $response = $this->renderException($request, $e);
} $this->app['events']->dispatch(
new Events\RequestHandled($request, $response)
); return $response;
}
protected function sendRequestThroughRouter($request)
{
$this->app->instance('request', $request); Facade::clearResolvedInstance('request'); //针对请求为应用程序'拔靴带' 执行bootstrap类的数组
//在请求处理阶段共有7个环节,每一个环节由一个类来实现的
//而且每个类都会有一个bootstrap()函数用于实现准备工作
$this->bootstrap(); return (new Pipeline($this->app))
->send($request)
->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
->then($this->dispatchToRouter());
}
/**
* Bootstrap the application for HTTP requests.
*
* @return void
*/
public function bootstrap()
{
if (! $this->app->hasBeenBootstrapped()) {
$this->app->bootstrapWith($this->bootstrappers());
}
}
\vendor\laravel\framework\src\Illuminate\Foundation\Application.php
public function bootstrapWith(array $bootstrappers)
{
$this->hasBeenBootstrapped = true; foreach ($bootstrappers as $bootstrapper) {
$this['events']->fire('bootstrapping: '.$bootstrapper, [$this]); $this->make($bootstrapper)->bootstrap($this); $this['events']->fire('bootstrapped: '.$bootstrapper, [$this]);
}
}
protected $bootstrappers = [
\Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class,
\Illuminate\Foundation\Bootstrap\LoadConfiguration::class,//环境检测与配置加载
\Illuminate\Foundation\Bootstrap\HandleExceptions::class,
\Illuminate\Foundation\Bootstrap\RegisterFacades::class,//外观注册
\Illuminate\Foundation\Bootstrap\RegisterProviders::class,//服务提供者注册
\Illuminate\Foundation\Bootstrap\BootProviders::class,//启动服务
];
接下来讲讲 服务提供者注册和启动服务
\Illuminate\Foundation\Bootstrap\RegisterProviders::class,//服务提供者注册
//服务提供者注册
public function bootstrap(Application $app)
{
$app->registerConfiguredProviders();
}
在Application中注册所有配置的服务提供者
public function registerConfiguredProviders()
{
$providers = Collection::make($this->config['app.providers'])
->partition(function ($provider) {
return Str::startsWith($provider, 'Illuminate\\');
}); $providers->splice(1, 0, [$this->make(PackageManifest::class)->providers()]); (new ProviderRepository($this, new Filesystem, $this->getCachedServicesPath()))
->load($providers->collapse()->toArray());
}
/**
* //注册应用的服务提供者
*
* @param array $providers
* @return void
*/
public function load(array $providers)
{
//加载Laravel\bootstrap\cache\services.json文件
$manifest = $this->loadManifest(); //加载服务清单,这里包含程序所有的服务提供者并进行分类
if ($this->shouldRecompile($manifest, $providers)) {
$manifest = $this->compileManifest($providers);
} //服务提供者加载时间,当这个事件发生时才自动加载这个服务提供者
foreach ($manifest['when'] as $provider => $events) {
$this->registerLoadEvents($provider, $events);
} //提前注册那些必须加载的服务提供者,以此为应用提供服务
foreach ($manifest['eager'] as $provider) {
$this->app->register($provider);
}
//在列表中江路延迟加载的服务提供者,需要时再加载
$this->app->addDeferredServices($manifest['deferred']);
}
服务提供者都继承于服务提供者基类(Illuminate\Support\ServiceProvider),该类是一个抽象类,其中定义了一个抽象函数register(),所以每个服务提供者都需要实现该函数,而该函数中实现了服务注册的内容
启动服务 在这最后一步中:服务提供者必须要实现register()函数,还有一个boot()函数根据需要决定是否实现,主要用于启动服务;对于boot()函数的服务提供者,会通过下面类统一管理调用
\Illuminate\Foundation\Bootstrap\BootProviders::class,//启动服务
public function bootstrap(Application $app)
{
$app->boot();
}
在服务容器vendor\laravel\framework\src\Illuminate\Foundation\Application.php代码中
public function boot()
{
if ($this->booted) {
return;
} $this->fireAppCallbacks($this->bootingCallbacks); array_walk($this->serviceProviders, function ($p) {
$this->bootProvider($p);
}); $this->booted = true; $this->fireAppCallbacks($this->bootedCallbacks);
} protected function bootProvider(ServiceProvider $provider)
{
if (method_exists($provider, 'boot')) {
return $this->call([$provider, 'boot']);
}
}
从上面可以看到,在 Larave !应用程序的服务容器中保存了服务提供者的实例数组,即 $serviceProviders 属性:
这单包含了服务容器实例化过程中注册的两个基础服务提供者及在服务提供者注册过程中注册的 eagc :类服务提供者,
然后通过代码“ $this->caIl([$provider,'boot']); $SserviceProviders 属性中记录的每一个服务提供者实例的 boot()函数,
该函数主要是对相应的服务进行初始化,
下一章节:中间件
laravel请求到响应的生命周期的更多相关文章
- Laravel学习:请求到响应的生命周期
Laravel请求到响应的整个执行过程,主要可以归纳为四个阶段,即程序启动准备阶段.请求实例化阶段.请求处理阶段.响应发送和程序终止阶段. 程序启动准备阶段 服务容器实例化 服务容器的实例化和基本注册 ...
- python---django请求-响应的生命周期(FBV和CBV含义)
Django请求的生命周期是指:当用户在访问该url路径是,在服务器Django后台都发生了什么. 客户端发送Http请求给服务端,Http请求是一堆字符串,其内容是: 访问:http://crm.o ...
- Laravel 入口文件解读及生命周期
这里只贴index.php的代码, 深入了解的请访问 https://laravel-china.org/articles/10421/depth-mining-of-laravel-life- ...
- ASP.NET MVC5 的请求管道和运行生命周期
https://www.jianshu.com/p/848fda7f79e0 请求处理管道 请求管道是一些用于处理HTTP请求的模块组合,在ASP.NET中,请求管道有两个核心组件:IHttpModu ...
- asp.net请求管道和页面生命周期
- Envoy 代理中的请求的生命周期
Envoy 代理中的请求的生命周期 翻译自Envoy官方文档. 目录 Envoy 代理中的请求的生命周期 术语 网络拓扑 配置 高层架构 请求流 总览 1.Listener TCP连接的接收 2.监听 ...
- Net6 DI源码分析Part5 在Kestrel内Di Scope生命周期是如何根据请求走的?
Net6 DI源码分析Part5 在Kestrel内Di Scope生命周期是如何根据请求走的? 在asp.net core中的DI生命周期有一个Scoped是根据请求走的,也就是说在处理一次请求时, ...
- asp.net MVC 应用程序的生命周期
下面这篇文章总结了 asp.net MVC 框架程序的生命周期.觉得写得不错,故转载一下. 转载自:http://www.cnblogs.com/yplong/p/5582576.html ...
- ASP.NET 页生命周期
ASP.NET 页运行时,此页将经历一个生命周期,在生命周期中将执行一系列处理步骤.这些步骤包括初始化.实例化控件.还原和维护状态.运行事件处理程序代码以及进行 呈现.了解页生命周期非常重要,因为这样 ...
随机推荐
- 利用mysql行级锁创建数据库主键id
存储函数: CREATE FUNCTION `getSerialNo`(`serialName` VARCHAR(50), `skip` INT) RETURNS bigint(20) COMMENT ...
- CSS-形变 动画 表格
一.形变 /*1.形变参考点: 三轴交界点*/ transform-origin: x轴坐标 y轴坐标; /*2.旋转 rotate deg*/ transform: rotate(720deg) ...
- python 操作剪切板
python3 在使用网上找到的一些使用剪切板的片段时发现存在写入剪切板后乱码的情况, 研究后发现python3不能使用SetClipboardData方法, 要使用SetClipboardText ...
- Servlet快速入门
servlet是运行在服务端的java小程序,用来处理客户端请求,响应给浏览器的动态资源 servlet规范:包含3个技术点 1.servlet技术 2.filter技术 3.listener技术 s ...
- C语言中的多线程编程
很久很久以前,我对C语言的了解并不是很多,我最早听说多线程编程是用Java,其实C语言也有多线程编程,而且更为简单.方便.强大.下面就让我们简单领略一下Unix C语言环境下的多线程编程吧! 下面先看 ...
- es6 export 和export default的区别
区别 export 每个文件中可使用多次export命令 import时需要知道所加载的变量名或函数名 import时需要使用{},或者整体加载方法 export export default 每个文 ...
- 学习笔记58—3D杯子设计
软件下载:http://www.i3done.com/ 界面如下: 3D杯子设计步骤(参考:http://www.i3done.com/news/video/402.html): 生成杯体 1.点击基 ...
- MySQL学习(七)
学习子查询 1 查出本网站最新的good_id最大的一条商品(要求取出商品名) mysql> select goos_id,goods_name from goods -> order b ...
- 配置java环境jdk
最近尝试改公司的项目中的一个后台管理系统,前后台都让我一个做,所以要配置一下java环境: 1. 按装jdk 1.6//2. 安装eclipse3. 安装maven4. 安装eclispe的maven ...
- lua闭包实现迭代器遍历数组
--实现访问数组的迭代器 function visit(t) return function() i = i + return t[i] end end --要访问的数组 ,,,} itor = vi ...