请求到响应的核个执行过程,主要可以归纳为四个阶段,即程序启动准备阶段、请求实例化阶段、请求处理阶段、响应发送和程序终止阶段。

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请求到响应的生命周期的更多相关文章

  1. Laravel学习:请求到响应的生命周期

    Laravel请求到响应的整个执行过程,主要可以归纳为四个阶段,即程序启动准备阶段.请求实例化阶段.请求处理阶段.响应发送和程序终止阶段. 程序启动准备阶段 服务容器实例化 服务容器的实例化和基本注册 ...

  2. python---django请求-响应的生命周期(FBV和CBV含义)

    Django请求的生命周期是指:当用户在访问该url路径是,在服务器Django后台都发生了什么. 客户端发送Http请求给服务端,Http请求是一堆字符串,其内容是: 访问:http://crm.o ...

  3. Laravel 入口文件解读及生命周期

    这里只贴index.php的代码, 深入了解的请访问    https://laravel-china.org/articles/10421/depth-mining-of-laravel-life- ...

  4. ASP.NET MVC5 的请求管道和运行生命周期

    https://www.jianshu.com/p/848fda7f79e0 请求处理管道 请求管道是一些用于处理HTTP请求的模块组合,在ASP.NET中,请求管道有两个核心组件:IHttpModu ...

  5. asp.net请求管道和页面生命周期

  6. Envoy 代理中的请求的生命周期

    Envoy 代理中的请求的生命周期 翻译自Envoy官方文档. 目录 Envoy 代理中的请求的生命周期 术语 网络拓扑 配置 高层架构 请求流 总览 1.Listener TCP连接的接收 2.监听 ...

  7. Net6 DI源码分析Part5 在Kestrel内Di Scope生命周期是如何根据请求走的?

    Net6 DI源码分析Part5 在Kestrel内Di Scope生命周期是如何根据请求走的? 在asp.net core中的DI生命周期有一个Scoped是根据请求走的,也就是说在处理一次请求时, ...

  8. asp.net MVC 应用程序的生命周期

    下面这篇文章总结了 asp.net MVC 框架程序的生命周期.觉得写得不错,故转载一下. 转载自:http://www.cnblogs.com/yplong/p/5582576.html       ...

  9. ASP.NET 页生命周期

    ASP.NET 页运行时,此页将经历一个生命周期,在生命周期中将执行一系列处理步骤.这些步骤包括初始化.实例化控件.还原和维护状态.运行事件处理程序代码以及进行 呈现.了解页生命周期非常重要,因为这样 ...

随机推荐

  1. Linux命令1——a

    addUser: -c:备注 -d:登陆目录 -e:有效期限 -f:缓冲天数 -g:组 -b:用户目录 -G:附加组 -s:制定使用默认的shell -u:指定用户ID -r:建立系统账号 -M:不自 ...

  2. NodeJS 获取网页源代码

    获取网页源代码 node 获取网页源代码 var http = require('http'); var url = "http://www.baidu.com/"; // 参数u ...

  3. BZOJ 1055: [HAOI2008]玩具取名(记忆化搜索)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1055 题意: 思路:记忆化搜索. #include<iostream> #include ...

  4. HDU 5792 World is Exploding(树状数组+离散化)

    http://acm.split.hdu.edu.cn/showproblem.php?pid=5792 题意: 思路: lmin[i]:表示左边比第i个数小的个数. lmax[i]:表示左边比第i个 ...

  5. Android之使用传感器获取相应数据

    Android的大部分手机中都有传感器,传感器类型有方向.加速度(重力).光线.磁场.距离(临近性).温度等. 方向传感器:   Sensor.TYPE_ORIENTATION 加速度(重力)传感器: ...

  6. 【Java】【THINK】

    1. 新建类,应优先考虑“组织”对象,而不是继承.这样可以保持清爽. 2. Java对象&对象句柄: 声明了一个类型的变量也就是声明了一个该类型的对象.但是这个对象只是个抽象的概念,并不会在内 ...

  7. 副本死亡传送(_instance_die_tele)

    玩家在副本中死亡时,将传送至对应的坐标 mapId 副本地图ID posId 坐标ID,对应_postion中posId

  8. c# 通过反射输出成员变量以及成员变量的值

    /*** @Author rexzhao* 工具类 仅限于* public variable*/using System.Collections;using System.Collections.Ge ...

  9. bzoj 1036: [ZJOI2008]树的统计Count 树链剖分+线段树

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 16294  Solved: 6645[Submit ...

  10. P3853 [TJOI2007]路标设置

    传送门 思路: 类似于数列分段的二分查找答案.设目前的 mid 是一个最小的“空旷指数”,那么在 sum 数组(路标数组)里每两个相邻间的路标距离一定要小于等于目前的 mid , 如果大于,那就必须使 ...