Laravel5.x启动过程分析
来源:互联网 发布:淘宝装修免费一键安装 编辑:程序博客网 时间:2024/06/05 06:19
1、初始化Application
// realpath(__DIR__.'/../') 为web应用目录// 如 D:\www\laravel5.1\$app = new Illuminate\Foundation\Application( realpath(__DIR__.'/../'));
接下来调用 Application类的构造方法
/** * Create a new Illuminate application instance. * * @param string|null $basePath * @return void */ public function __construct($basePath = null) { // 注册基本绑定 这一步主要是把app和Illuminate\Container\Container指向Application实例,并添加到instances属性里 $this->registerBaseBindings(); // 注册基本服务提供者,添加到bindings属性里 $this->registerBaseServiceProviders(); // 注册核心类的别名, 添加到aliases属性里 $this->registerCoreContainerAliases(); // 设置根路径,添加到instances属性里 if ($basePath) { $this->setBasePath($basePath); } }
1.1 注册基本绑定
/** * Register the basic bindings into the container. * * @return void */ protected function registerBaseBindings() { // $this Application实例 static::setInstance($this); // app指向Illuminate\Foundation\Application实例 $this->instance('app', $this); // Illuminate\Container\Container指向Illuminate\Foundation\Application实例 $this->instance('Illuminate\Container\Container', $this); //dd($this->instances); }
输出$this->instances结果为:
array:2 [▼ "app" => Application {#2 ▶} "Illuminate\Container\Container" => Application {#2 ▶}]
1.2 注册基本服务提供者
/** * Register all of the base service providers. * * @return void */ protected function registerBaseServiceProviders() { // 注册事件服务提供者 $this->register(new EventServiceProvider($this)); // 注册路由服务提供者 $this->register(new RoutingServiceProvider($this)); }
EventServiceProvider 继承 Illuminate\Support\ServiceProvider类,实例化时会先调用ServiceProvider的构造方法
/** * Create a new service provider instance. * * @param \Illuminate\Contracts\Foundation\Application $app * @return void */ public function __construct($app) { // 将Application实例赋值给当前对象的成员变量 $this->app = $app; }
register方法
/** * Register a service provider with the application. * * @param \Illuminate\Support\ServiceProvider|string $provider * @param array $options * @param bool $force * @return \Illuminate\Support\ServiceProvider */ public function register($provider, $options = [], $force = false) { if ($registered = $this->getProvider($provider) && ! $force) { return $registered; } // If the given "provider" is a string, we will resolve it, passing in the // application instance automatically for the developer. This is simply // a more convenient way of specifying your service provider classes. if (is_string($provider)) { $provider = $this->resolveProviderClass($provider); } // 这里调用的是EventServiceProvider类的register方法 $provider->register(); // Once we have registered the service we will iterate through the options // and set each of them on the application so they will be available on // the actual loading of the service objects and for developer usage. foreach ($options as $key => $value) { $this[$key] = $value; } $this->markAsRegistered($provider); // If the application has already booted, we will call this boot method on // the provider class so it has an opportunity to do its boot logic and // will be ready for any usage by the developer's application logics. if ($this->booted) { $this->bootProvider($provider); } return $provider; }
EventServiceProvider类的register方法
/** * Register the service provider. * * @return void */ public function register() { // 调用Application实例的singleton方法,该方法继承自 // Illuminate\Container\Container.php $this->app->singleton('events', function ($app) { return (new Dispatcher($app))->setQueueResolver(function () use ($app) { return $app->make('Illuminate\Contracts\Queue\Factory'); }); }); } /** * Register a shared binding in the container. * * @param string|array $abstract * @param \Closure|string|null $concrete * @return void */ public function singleton($abstract, $concrete = null) { // 注册绑定 $this->bind($abstract, $concrete, true); }
在bind方法中将event添加到 binding中
$this->bindings[$abstract] = compact('concrete', 'shared');
这时输出$this->bindings结果如下
array:1 [▼ "events" => array:2 [▼ "concrete" => Closure {#4 ▶} "shared" => true ]]
markAsRegistered方法
/** * Mark the given provider as registered. * * @param \Illuminate\Support\ServiceProvider $provider * @return void */ protected function markAsRegistered($provider) { // 这里要特别主要 $this['events'],调用的是数组中不存在的key $this['events']->fire($class = get_class($provider), [$provider]); $this->serviceProviders[] = $provider; $this->loadedProviders[$class] = true; }
注:因为该类实现了 ArrayAccess接口,当调用数组中不存在的key时,会调用 ArrayAccess::offsetGet 方法(具体自行参考PHP参考文档ArrayAccess),这个方法在Illuminate\Container\Container.php中实现
/** * Get the value at a given offset. * * @param string $key * @return mixed */ public function offsetGet($key) { return $this->make($key); }
接下来的部分是RoutingServiceProvider
/** * Register the service provider. * * @return void */ public function register() { $this->registerRouter(); $this->registerUrlGenerator(); $this->registerRedirector(); $this->registerPsrRequest(); $this->registerPsrResponse(); $this->registerResponseFactory(); //dd($this->app); }
这部分的目的主要是绑定关系,从输出结果我们可以明显看出
Application {#2 ▼ #basePath: null #hasBeenBootstrapped: false #booted: false #bootingCallbacks: [] #bootedCallbacks: [] #terminatingCallbacks: [] #serviceProviders: array:1 [▶] #loadedProviders: array:1 [▶] #deferredServices: [] #monologConfigurator: null #databasePath: null #storagePath: null #environmentPath: null #environmentFile: ".env" #namespace: null #resolved: array:1 [▶] #bindings: array:7 [▼ "events" => array:2 [▶] "router" => array:2 [▶] "url" => array:2 [▶] "redirect" => array:2 [▶] "Psr\Http\Message\ServerRequestInterface" => array:2 [▶] "Psr\Http\Message\ResponseInterface" => array:2 [▶] "Illuminate\Contracts\Routing\ResponseFactory" => array:2 [▶] ]
注:在调用registerRouter方法时,也就是下面这段代码
/** * Register the router instance. * * @return void */ protected function registerRouter() { // 这里是一个赋值操作,因为实现了ArrayAccess接口,如果$this->app['router']不存在,则会调用ArrayAccess::offsetSet方法,也就是(Illuminate\Container\Container.php里的offsetSet方法)。 $this->app['router'] = $this->app->share(function ($app) { return new Router($app['events'], $app); }); }
1.3 注册核心类别名
通过输出$this->app得到以下结果,在aliases数组中可以看到对应关系
Application {#2 ▼ #basePath: null #hasBeenBootstrapped: false #booted: false #bootingCallbacks: [] #bootedCallbacks: [] #terminatingCallbacks: [] #serviceProviders: array:2 [▶] #loadedProviders: array:2 [▶] #deferredServices: [] #monologConfigurator: null #databasePath: null #storagePath: null #environmentPath: null #environmentFile: ".env" #namespace: null #resolved: array:1 [▶] #bindings: array:7 [▶] #instances: array:3 [▶] #aliases: array:59 [▼ "Illuminate\Foundation\Application" => "app" "Illuminate\Contracts\Container\Container" => "app" "Illuminate\Contracts\Foundation\Application" => "app" "Illuminate\Auth\AuthManager" => "auth" "Illuminate\Auth\Guard" => "auth.driver" "Illuminate\Contracts\Auth\Guard" => "auth.driver" "Illuminate\Auth\Passwords\TokenRepositoryInterface" => "auth.password.tokens" "Illuminate\View\Compilers\BladeCompiler" => "blade.compiler" "Illuminate\Cache\CacheManager" => "cache" "Illuminate\Contracts\Cache\Factory" => "cache" "Illuminate\Cache\Repository" => "cache.store" "Illuminate\Contracts\Cache\Repository" => "cache.store" "Illuminate\Config\Repository" => "config" "Illuminate\Contracts\Config\Repository" => "config" "Illuminate\Cookie\CookieJar" => "cookie" "Illuminate\Contracts\Cookie\Factory" => "cookie" "Illuminate\Contracts\Cookie\QueueingFactory" => "cookie" "Illuminate\Encryption\Encrypter" => "encrypter" "Illuminate\Contracts\Encryption\Encrypter" => "encrypter" "Illuminate\Database\DatabaseManager" => "db" "Illuminate\Database\Connection" => "db.connection" "Illuminate\Database\ConnectionInterface" => "db.connection" "Illuminate\Events\Dispatcher" => "events" "Illuminate\Contracts\Events\Dispatcher" => "events" "Illuminate\Filesystem\Filesystem" => "files" "Illuminate\Filesystem\FilesystemManager" => "filesystem" "Illuminate\Contracts\Filesystem\Factory" => "filesystem" "Illuminate\Contracts\Filesystem\Filesystem" => "filesystem.disk" "Illuminate\Contracts\Filesystem\Cloud" => "filesystem.cloud" "Illuminate\Contracts\Hashing\Hasher" => "hash" "Illuminate\Translation\Translator" => "translator" "Symfony\Component\Translation\TranslatorInterface" => "translator" "Illuminate\Log\Writer" => "log" "Illuminate\Contracts\Logging\Log" => "log" "Psr\Log\LoggerInterface" => "log" "Illuminate\Mail\Mailer" => "mailer" "Illuminate\Contracts\Mail\Mailer" => "mailer" "Illuminate\Contracts\Mail\MailQueue" => "mailer" "Illuminate\Auth\Passwords\PasswordBroker" => "auth.password" "Illuminate\Contracts\Auth\PasswordBroker" => "auth.password" "Illuminate\Queue\QueueManager" => "queue" "Illuminate\Contracts\Queue\Factory" => "queue" "Illuminate\Contracts\Queue\Monitor" => "queue" "Illuminate\Contracts\Queue\Queue" => "queue.connection" "Illuminate\Routing\Redirector" => "redirect" "Illuminate\Redis\Database" => "redis" "Illuminate\Contracts\Redis\Database" => "redis" "Illuminate\Http\Request" => "request" "Illuminate\Routing\Router" => "router" "Illuminate\Contracts\Routing\Registrar" => "router" "Illuminate\Session\SessionManager" => "session" "Illuminate\Session\Store" => "session.store" "Symfony\Component\HttpFoundation\Session\SessionInterface" => "session.store" "Illuminate\Routing\UrlGenerator" => "url" "Illuminate\Contracts\Routing\UrlGenerator" => "url" "Illuminate\Validation\Factory" => "validator" "Illuminate\Contracts\Validation\Factory" => "validator" "Illuminate\View\Factory" => "view" "Illuminate\Contracts\View\Factory" => "view" ]
1.4 设置根路径
#instances: array:10 [▼ "app" => Application {#2} "Illuminate\Container\Container" => Application {#2} "events" => Dispatcher {#5 ▶} "path" => "D:\www\laravel5.1\app" "path.base" => "D:\www\laravel5.1" "path.config" => "D:\www\laravel5.1\config" "path.database" => "D:\www\laravel5.1\database" "path.lang" => "D:\www\laravel5.1\resources\lang" "path.public" => "D:\www\laravel5.1\public" "path.storage" => "D:\www\laravel5.1\storage" ]
2、注册共享的Kernel和异常处理器
$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);
上述代码将绑定关系添加到bindings属性里,里面的::class 是php新增的静态属性
#bindings: array:10 [▼ "events" => array:2 [▶] "router" => array:2 [▶] "url" => array:2 [▶] "redirect" => array:2 [▶] "Psr\Http\Message\ServerRequestInterface" => array:2 [▶] "Psr\Http\Message\ResponseInterface" => array:2 [▶] "Illuminate\Contracts\Routing\ResponseFactory" => array:2 [▶] "Illuminate\Contracts\Http\Kernel" => array:2 [▶] "Illuminate\Contracts\Console\Kernel" => array:2 [▶] "Illuminate\Contracts\Debug\ExceptionHandler" => array:2 [▶] ]
3、处理请求和响应
这时我们获取$app后返回index.php页面,然后执行
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
这里要注意,make方法调用的是子类Illuminate\Foundation\Application.php里的方法,然后在调用父类Illuminate\Container\Container.php的make方法
接着是make方法里的
// 这里返回bindings数组里的数据,因为我们在获取$app的时候已经把// "Illuminate\Contracts\Http\Kernel"绑定了$concrete = $this->getConcrete($abstract);
接着我们调用$object = $this->build($concrete, $parameters);
这build方法中
if ($concrete instanceof Closure) { return $concrete($this, $parameters); }
因为$concrete是闭包,所以直接返回,这里调用的是我们绑定在app里的闭包也就是,
“Illuminate\Contracts\Http\Kernel” => array:2 [▼
“concrete” => Closure {#23 ▼
class: “Illuminate\Container\Container”
this: Application {#2}
parameters: array:2 [▶]
use: array:2 [▼
“$abstract” => “Illuminate\Contracts\Http\Kernel”
“$concrete” => “App\Http\Kernel”
]
file: “D:\www\laravel5.1\vendor\laravel\framework\src\Illuminate\Container\Container.php”
line: “222 to 226”
}
“shared” => true
]
执行这个方法
function ($c, $parameters = []) use ($abstract, $concrete) { // 根据上述use中的参数,这里赋值应该是make $method = ($abstract == $concrete) ? 'build' : 'make'; // 然后在调用application.php中的make方法,$concrete对应的就是App\Http\Kernel return $c->$method($concrete, $parameters); }
最终是调用构造函数设置
Kernel {#24 ▼ #middleware: array:6 [▼ 0 => "Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode" 1 => "App\Http\Middleware\EncryptCookies" 2 => "Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse" 3 => "Illuminate\Session\Middleware\StartSession" 4 => "Illuminate\View\Middleware\ShareErrorsFromSession" 5 => "App\Http\Middleware\VerifyCsrfToken" ] #routeMiddleware: array:4 [▼ "auth" => "App\Http\Middleware\Authenticate" "auth.basic" => "Illuminate\Auth\Middleware\AuthenticateWithBasicAuth" "guest" => "App\Http\Middleware\RedirectIfAuthenticated" "test" => "App\Http\Middleware\TestMiddleware" ] #app: Application {#2 ▶} #router: Router {#88 ▶} #bootstrappers: array:7 [▶]}
接下来是处理web请求的核心部分 handle方法
$response = $kernel->handle( // $request是经过Symfony封装的请求对象 $request = Illuminate\Http\Request::capture());
调用bootstrap方法,启动一系列启动类的bootstrap(定义在\Illuminate\Foundation\Http\Kernel.php中)方法:
protected $bootstrappers = [ // 该类用来读取.env定义的变量 环境配置($app[‘env’]) 'Illuminate\Foundation\Bootstrap\DetectEnvironment', // 扫描config文件下的所有.php结尾的配置文件 基本配置($app[‘config’]) 'Illuminate\Foundation\Bootstrap\LoadConfiguration', // 日志文件($app[‘log’]) 'Illuminate\Foundation\Bootstrap\ConfigureLogging', // 错误&异常处理 'Illuminate\Foundation\Bootstrap\HandleExceptions', //清除已解析的Facade并重新启动,注册config文件中alias定义的所有Facade类到容器 (定义在配置文件app.php中的aliases数组) 'Illuminate\Foundation\Bootstrap\RegisterFacades', //注册config中providers定义的所有Providers类到容器 (定义在配置文件app.php中的providers数组) 'Illuminate\Foundation\Bootstrap\RegisterProviders', //调用所有已注册Providers的boot方法 'Illuminate\Foundation\Bootstrap\BootProviders', ];
通过Pipeline发送请求,经过中间件,再由路由转发,最终返回响应
new Pipeline($this->app)) ->send($request) ->through($this->middleware) ->then($this->dispatchToRouter()
将响应信息发送到浏览器:
$response->send();
处理继承自TerminableMiddleware接口的中间件(Session)并结束应用生命周期:
$kernel->terminate($request, $response);
- Laravel5.x启动过程分析
- x-loader启动过程分析
- Laravel5.5源码详解 -- 数据库的启动与连接过程
- 源码分析vxWorks6.x的ARM板BSP启动过程
- Laravel5.5源码详解 -- Session的启动分析
- cocos2d-x启动过程
- Angular1.x启动分析
- laravel5.1启动详解
- laravel5搭建过程问题
- CDlinux启动过程分析
- UBOOT启动过程分析
- startx启动过程分析
- DM642启动过程分析
- BIOS启动过程分析
- startx启动过程分析
- 2440启动过程分析
- linxu 启动过程分析
- startx启动过程分析
- 取消交互
- 依赖注入的方式和注入的配置实例
- maven+proguard第三方jar打包混淆
- 小记录
- python爬虫
- Laravel5.x启动过程分析
- Linux下Socket编程函数格式详解
- Android--LayoutInflater解析
- Hibernate 性能优化
- Java的Spi机制心得
- 安全字符串函数stringcchXXX与 stringcbXXX什么区别?
- MyBatis的动态SQL详解
- CookieUtils
- MyBatis 解决字段名与实体类属性名不相同的冲突