Skip to main content

服务提供者初始化引导

简介

前面几个章节,我们把如下图前五个引导启动讲解完毕,今天我们就看最后一个:BootProviders

file

正文

  • 首先看 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 都有什么吧

    file

    一共 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 方法。。。