请求到响应的核个执行过程,主要可以归纳为四个阶段,即程序启动准备阶段、请求实例化阶段、请求处理阶段、响应发送和程序终止阶段。
public\index.php中有这么一段代码
$app = require_once __DIR__.'/../bootstrap/app.php';
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | //app.php<br><?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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | public function __construct( $basePath = null) { if ( $basePath ) { //注册应用的基础路径 $this ->setBasePath( $basePath ); } //用来绑定基础服务,主要是绑定容器实例本身,是的其它对象可以很容易得到服务容器实例 $this ->registerBaseBindings(); //注册基础服务提供者 $this ->registerBaseServiceProviders(); //注册核心类别名和应用的基础路径 $this ->registerCoreContainerAliases(); } |
setBasePath
1 2 3 4 5 6 7 8 | public function setBasePath( $basePath ) { $this ->basePath = rtrim( $basePath , '\/' ); //在容器中绑定应用程序的基础路径 $this ->bindPathsInContainer(); return $this ; } |
registerBaseBindings
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | 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 :定义了整个框架的核心服务别名
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | 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
/**
* 主要实现了服务容器的实例化和基本注册
*包括服务容器本身的注册,基础服务提供者注册,核心类别名注册和基本路径注册
*
*/
1 2 3 4 5 6 7 | $kernel = $app ->make(Illuminate\Contracts\Http\Kernel:: class ); //处理请求 $response = $kernel ->handle( //请求实例的创建 $request = Illuminate\Http\Request::capture() ); |
namespace Illuminate\Foundation\Http\Kernel
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | /** * 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 ; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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()); } |
1 2 3 4 5 6 7 8 9 10 11 | /** * 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
1 2 3 4 5 6 7 8 9 10 11 12 | 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 ]); } } |
1 2 3 4 5 6 7 8 | 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中注册所有配置的服务提供者
1 2 3 4 5 6 7 8 9 10 11 12 | 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()); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | /** * //注册应用的服务提供者 * * @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,//启动服务
1 2 3 4 | public function bootstrap(Application $app ) { $app ->boot(); } |
在服务容器vendor\laravel\framework\src\Illuminate\Foundation\Application.php代码中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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()函数,
该函数主要是对相应的服务进行初始化,
下一章节:中间件
本文来自博客园,作者:孙龙-程序员,转载请注明原文链接:https://www.cnblogs.com/sunlong88/p/9355010.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能