龙空技术网

[ Laravel 5.6 文档 ] 底层原理 —— 服务提供者

阿牛哥Gx 79

前言:

如今同学们对“laravel路由实现原理”大体比较着重,你们都想要了解一些“laravel路由实现原理”的相关内容。那么小编也在网络上搜集了一些对于“laravel路由实现原理””的相关文章,希望咱们能喜欢,各位老铁们快快来了解一下吧!

[ Laravel 5.6 文档 ] 底层原理 —— 服务提供者

我们所谓的“启动”指的是什么?这意味着注册服务,所有 Laravel 的核心服务都是通过服务提供者启动,服务提供者是应用配置的中心。

通过本文档,你将会学习如何编写自己的服务提供者并在 Laravel 应用中注册它们。【文章转自laravel学院】

简介

服务提供者是 Laravel 应用启动的中心,你自己的应用以及所有 Laravel 的核心服务都是通过服务提供者启动。

但是,我们所谓的“启动”指的是什么?通常,这意味着注册服务,包括注册服务容器绑定、事件监听器、中间件甚至路由。服务提供者是应用配置的中心。

如果你打开 Laravel 自带的 config/app.php 文件,将会看到一个 providers 数组,这里就是应用所要加载的所有服务提供者类,当然,其中很多是延迟加载的,也就是说不是每次请求都会被加载,只有真的用到它们的时候才会加载。

通过本文档,你将会学习如何编写自己的服务提供者并在 Laravel 应用中注册它们。

编写服务提供者

所有的服务提供者都继承自 Illuminate\Support\ServiceProvider 类。大部分服务提供者都包含两个方法: registerboot 。在 register 方法中,你唯一要做的事情就是绑定服务到服务容器,不要尝试在该方法中注册事件监听器,路由或者任何其它功能。

通过 Artisan 命令 make:provider 即可生成一个新的提供者:php artisan make:provider RiakServiceProvider

register 方法

正如前面所提到的,在 register 方法中只绑定服务到服务容器,而不要做其他事情,否则,一不小心就可能用到一个尚未被加载的服务提供者提供的服务。

现在让我们来看看一个基本的服务提供者长什么样:

<?phpnamespace App\Providers;use Riak\Connection;use Illuminate\Support\ServiceProvider;class RiakServiceProvider extends ServiceProvider{ /** * 在容器中注册绑定. * * @return void */ public function register() { $this->app->singleton(Connection::class, function ($app) { return new Connection(config('riak')); }); }}

该服务提供者只定义了一个 register 方法,并使用该方法在服务容器中定义了一个 Riak\Connection 的实现。如果你不知道服务容器是如何工作的,请参考其文档。

bindings 和 singletons 属性

如果你的服务提供者注册了很多简单的绑定,你可能希望使用 bindingssingletons 属性来替代手动注册每个容器绑定以简化代码。当服务提供者被框架加载后,会自动检查这些属性并注册相应绑定:

<?phpnamespace App\Providers;use App\Contracts\ServerProvider;use App\Contracts\DowntimeNotifier;use Illuminate\Support\ServiceProvider;use App\Services\PingdomDowntimeNotifier;use App\Services\DigitalOceanServerProvider;class AppServiceProvider extends ServiceProvider{ /** * All of the container bindings that should be registered. * * @var array */ public $bindings = [ ServerProvider::class => DigitalOceanServerProvider::class, ]; /** * All of the container singletons that should be registered. * * @var array */ public $singletons = [ DowntimeNotifier::class => PingdomDowntimeNotifier::class, ];}

boot 方法

如果我们想要在服务提供者中注册视图 composer 该怎么做?这就要用到 boot 方法了。该方法在所有服务提供者被注册以后才会被调用,这就是说我们可以在其中访问框架已注册的所有其它服务:

<?phpnamespace App\Providers;use Illuminate\Support\ServiceProvider;class ComposerServiceProvider extends ServiceProvider{ /** * Perform post-registration booting of services. * * @return void */ public function boot() { view()->composer('view', function () { // }); }}

boot 方法的依赖注入

我们可以在 boot 方法中对依赖进行类型提示,服务容器会自动注入你所需要的依赖:

use Illuminate\Contracts\Routing\ResponseFactory;public function boot(ResponseFactory $response){ $response->macro('caps', function ($value) { // });}
注册服务提供者

所有服务提供者都是通过配置文件 config/app.php 中进行注册,该文件包含了一个列出所有服务提供者名字的 providers 数组,默认情况下,其中列出了所有核心服务提供者,这些服务提供者启动 Laravel核心组件,比如邮件、队列、缓存等等。

要注册你自己的服务提供者,只需要将其追加到该数组中即可:

'providers' => [ // 其它服务提供者 App\Providers\ComposerServiceProvider::class,],
延迟加载服务提供者

如果你的提供者仅仅只是在服务容器中注册绑定,你可以选择延迟加载该绑定直到注册绑定的服务真的需要时再加载,延迟加载这样的一个提供者将会提升应用的性能,因为它不会在每次请求时都从文件系统加载。

Laravel 编译并保存所有延迟服务提供者提供的服务及服务提供者的类名。然后,只有当你尝试解析其中某个服务时 Laravel 才会加载其服务提供者。

想要延迟加载一个提供者,设置 defer 属性为 true 并定义一个 provides 方法,该方法返回该提供者注册的服务容器绑定:

<?phpnamespace App\Providers;use Riak\Connection;use Illuminate\Support\ServiceProvider;class RiakServiceProvider extends ServiceProvider{ /** * 服务提供者加是否延迟加载. * * @var bool */ protected $defer = true; /** * 注册服务提供者 * * @return void */ public function register() { $this->app->singleton(Connection::class, function ($app) { return new Connection($app['config']['riak']); }); } /** * 获取由提供者提供的服务. * * @return array */ public function provides() { return [Connection::class]; }}

注:强烈推荐阅读深入理解控制反转(IoC)和依赖注入(DI)深入理解服务容器和服务提供者的实现原理。

标签: #laravel路由实现原理