服务提供者初始化引导
简介
前面几个章节,我们把如下图前五个引导启动讲解完毕,今天我们就看最后一个:BootProviders
正文
首先看
BootProviders
类的bootstrap
方法class BootProviders
{
/**
* Bootstrap the given application.
*
* @param \Illuminate\Contracts\Foundation\Application $app
* @return void
*/
public function bootstrap(Application $app)
{
$app->boot();
}
}很清晰,表面上简简单单调用了容器对象的
boot
方法,那我们就看boot
方法干了什么吧boot 方法源码如下
public function boot()
{
// 首先判断应用之前有无加载过,如果加载过,直接返回
if ($this->booted) {
return;
}
// 读取 bootingCallbacks 属性数组,调用数组中的回调函数。作用就是执行一系列服务引导前的一些自定义行为
$this->fireAppCallbacks($this->bootingCallbacks);
// 此行为核心,下面将做详细说明
array_walk($this->serviceProviders, function ($p) {
$this->bootProvider($p);
});
// 将有无加载的开关改为 true ,防止二次加载
$this->booted = true;
// 执行服务引导后的一些自定义行为
$this->fireAppCallbacks($this->bootedCallbacks);
}关于上面代码说到的核心
array_walk($this->serviceProviders, function ($p) {
$this->bootProvider($p);
});array_walk
:官方说明是指使用用户自定义函数对数组中的每个元素做回调处理也就是说,将
$this->serviceProviders
数组的每个元素分别当做参数调用后面的闭包函数我们看一下
$this->serviceProviders
都有什么吧一共 19 个服务提供者对象。、
那么
$this->bootProvider($p);
到底对每个服务提供者对象干了什么呢。其实就是看看这些服务提供者对象有没有boot
方法,如果有,则执行一下这个方法,如果没有,就跳过,继续处理下一个服务提供者。下面我先对这 19 个服务提供者简要说明,重点说明它有没有
boot
方法Illuminate\Events\EventServiceProvider
: 系统事件服务提供者,就是用来 Application 初始化时绑定events
别名;没有boot
方法Illuminate\Log\LogServiceProvider
:系统日志服务提供者;没有boot
方法Illuminate\Routing\RoutingServiceProvider
:系统路由服务提供者;没有boot
方法Illuminate\Auth\AuthServiceProvider
:系统用户授权服务提供者;没有boot
方法Illuminate\Cookie\CookieServiceProvider
:系统 Cookie 服务提供者;没有boot
方法Illuminate\Database\DatabaseServiceProvider
:系统数据库服务提供者;有boot
方法先瞅一眼源码
public function boot()
{
Model::setConnectionResolver($this->app['db']);
Model::setEventDispatcher($this->app['events']);
}Illuminate\Encryption\EncryptionServiceProvider
:系统加解密服务提供者;没有boot
方法Illuminate\Filesystem\FilesystemServiceProvider
:系统文件处理服务提供者;没有boot
方法Illuminate\Foundation\Providers\FormRequestServiceProvider
:系统表单处理服务提供者;有boot
方法瞅一眼源码
public function boot()
{
$this->app->afterResolving(ValidatesWhenResolved::class, function ($resolved) {
$resolved->validateResolved();
});
$this->app->resolving(FormRequest::class, function ($request, $app) {
$request = FormRequest::createFrom($app['request'], $request);
$request->setContainer($app)->setRedirector($app->make(Redirector::class));
});
}
Illuminate\Foundation\Providers\FoundationServiceProvider
:系统基类服务提供者;没有boot
方法Illuminate\Notifications\NotificationServiceProvider
:系统通知服务提供者;有boot
方法源码
public function boot()
{
$this->loadViewsFrom(__DIR__.'/resources/views', 'notifications');
if ($this->app->runningInConsole()) {
$this->publishes([
__DIR__.'/resources/views' => $this->app->resourcePath('views/vendor/notifications'),
], 'laravel-notifications');
}
}Illuminate\Pagination\PaginationServiceProvider
:系统分页服务提供者:有boot
方法源码
public function boot()
{
$this->loadViewsFrom(__DIR__.'/resources/views', 'pagination');
if ($this->app->runningInConsole()) {
$this->publishes([
__DIR__.'/resources/views' => $this->app->resourcePath('views/vendor/pagination'),
], 'laravel-pagination');
}
}Illuminate\Session\SessionServiceProvider
:系统Session服务提供者:没有boot
方法Illuminate\View\ViewServiceProvider
:系统视图服务提供者:没有boot
方法Fideloper\Proxy\TrustedProxyServiceProvider
:系统可信代理服务提供者:有boot
方法public function boot()
{
$source = realpath($raw = __DIR__.'/../config/trustedproxy.php') ?: $raw;
if ($this->app instanceof LaravelApplication && $this->app->runningInConsole()) {
$this->publishes([$source => config_path('trustedproxy.php')]);
} elseif ($this->app instanceof LumenApplication) {
$this->app->configure('trustedproxy');
}
if ($this->app instanceof LaravelApplication && ! $this->app->configurationIsCached()) {
$this->mergeConfigFrom($source, 'trustedproxy');
}
}
```
App\Providers\AppServiceProvider
:可供用户自行定义应用的服务提供者;有boot
方法源码是空的,需要你来根据项目实际和官方文档进行添加
public function boot()
{
//
}App\Providers\AuthServiceProvider
:可自行定义的授权服务提供者:有boot
方法源码
public function boot()
{
$this->registerPolicies();
//
}App\Providers\EventServiceProvider
:可自行定义的事件服务提供者:有boot
方法源码
public function boot()
{
parent::boot();
//
}App\Providers\RouteServiceProvider
:可自定义的路由服务提供者:有boot
方法这个服务提供者的 boot 方法就是处理你在 web 或 api 中写的路由,将路由信息绑定到容器中,就是这个 boot 方法所做的,之后我会详细对这块进行说明
public function boot()
{
//
parent::boot();
}
写在最后
关于那些没有 boot 方法的服务提供者,其实都做了一样的事情,就是作为实际服务实体与容器实体之间的运输车或者桥梁,将服务实体与容器实体绑定在一起,因为这些服务提供者都一个叫 register 方法。。。