https://learnku.com/articles/6189/laravel-service-provider-detailed-concept-收藏一下

我们知道, Container 有很多种 「绑定」 的姿势,比如 bind() , extend() , singleton() , instance() 等等,那么 Laravel 中怎样「注册」这些「绑定」呢?那就是 Service Provider

先看下 Laravel 文档中这句话:

Service providers are the central place of all Laravel application bootstrapping. Your own application, as well as all of Laravel's core services are bootstrapped via service providers.

Service Providers (服务提供者) 是 Laravel 「引导」过程的核心。这个「引导」过程可以理解成「电脑从按下开机按钮到完全进入桌面」这段时间系统干的事。

概览

Service Provider 有两个重要的方法:

namespace App\Providers;
use Illuminate\Support\ServiceProvider;class AppServiceProvider extends ServiceProvider
{/*** 注册服务.** @return void*/public function register(){//}/*** 引导服务。** @return void*/public function boot(){//}
}

Laravel 在「引导」过程中干了两件重要的事:

  1. 通过 Service Provider 的 register() 方法注册「绑定」
  2. 所有 Servier Provider 的 register() 都执行完之后,再通过它们 boot() 方法,干一些别的事。

过程分析

这个「先后顺序」可以在 Laravel 的启动过程中找到:

  1. 首先,生成核心 Container : $app (实例化过程中还注册了一大堆基本的「绑定])。
    public/index.php

    /*
    |--------------------------------------------------------------------------
    | Turn On The Lights
    |--------------------------------------------------------------------------
    |
    */
    $app = require_once __DIR__.'/../bootstrap/app.php';
// bootstrap/app.php
$app = new Illuminate\Foundation\Application(realpath(__DIR__.'/../')
);
  1. 接下来注册 Http\Kernel , Console\Kernel , Debug\ExecptionHandler 三个「单例」绑定。
    bootstrap/app.php :

    $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
    );
  2. 然后「启动」应用。
    public/index.php

    /*
    |--------------------------------------------------------------------------
    | Run The Application
    |--------------------------------------------------------------------------
    |
    */
    $kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
    $response = $kernel->handle(
    $request = Illuminate\Http\Request::capture()
    );
  3. 由于以前的「绑定」,$kernel 获取的其实是 App\Http\Kernel 类的实例,App\Http\Kernel 类又继承了 Illuminate\Foundation\Http\Kernel 类。
    其 handle() 方法执行了 sendRequestThroughRouter() 方法:

// Illuminate\Foundation\Http
class Kernel implements KernelContract
{public function handle($request)try {//...$response = $this->sendRequestThroughRouter($request);} catch (Exception $e) {//...}}
}
  1. 这个 sendRequestThroughRouter() 方法执行了一系列 bootstrappers (引导器)

    // Illuminate\Foundation\Http
    class Kernel implements KernelContract
    {
    protected function sendRequestThroughRouter($request)
    {//...// 按顺序执行每个 bootstrapper$this->bootstrap();//...
    }
    }
  2. bootstrap() 方法中又调用了 Illuminate\Foundation\Application 类的 bootstrapWith() 方法:

// Illuminate\Foundation\Http
class Kernel implements KernelContract
{public function bootstrap(){if (! $this->app->hasBeenBootstrapped()) {//$this->app->bootstrapWith($this->bootstrappers());}}
}
// Illuminate\Foundation\Http\Kernel
class Kernel implements KernelContract
{protected $bootstrappers = [//...\Illuminate\Foundation\Bootstrap\RegisterProviders::class,  // 注册 Providers\Illuminate\Foundation\Bootstrap\BootProviders::class,  // 引导 Providers];protected function bootstrappers(){return $this->bootstrappers;}
}

这里就能看出来 Service Provider 中 register 和 boot 的「先后顺序了」。

后续的执行过程暂时先不介绍了。

这就意味着,在 Service Provider boot 之前,已经把注册好了所有服务的「绑定」。因此, 在 boot()方法中可以使用任何已注册的服务。
例如:

{
namespace App\Providers;
use Illuminate\Support\ServiceProvider;class ComposerServiceProvider extends ServiceProvider
{public function boot(){// 这里使用 make() 方法,可以更直观$this->app->make('view')->composer('view', function () {//});// 或者使用 view() 辅助函数view()->composer('view', function () {//});}
}

如果了解 Container 「绑定」 和 make 的概念,应该很容易理解上面的过程。

剩余的无非就是:

创建 Service Provier

php artisan make:provider MyServiceProvider

注册绑定

namespace App\Providers;
use Illuminate\Support\ServiceProvider;class MyServiceProvider extends ServiceProvider
{public function register(){$this->app->bind(MyInterface::class, MyClass::class);}
}

引导方法

namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Contracts\Routing\ResponseFactory;class MyServiceProvider extends ServiceProvider
{/*** boot() 方法中可以使用依赖注入。* 这是因为在 Illuminate\Foundation\Application 类中,* 通过 bootProvider() 方法中的 $this->call([$provider, 'boot']) * 来执行 Service Provider 的 boot() 方法* Container 的 call() 方法作用,可以参考上一篇文章*/public function boot(ResponseFactory $response){$response->macro('caps', function ($value) {//});}
}

在 config/app.php 中注册 Service Provider

'providers' => [/** Laravel Framework Service Providers...*//** Package Service Providers...*//** Application Service Providers...*/App\Providers\MyServiceProvider::class,
],

注意:Laravel 5.5 之后有 package discovery 功能的 package 不需要在 config/app.php 中注册。

延时加载

按需加载,只有当 Container 「make」 ServiceProvider 类 providers() 方法中返回的值时,才会加载此 ServiceProvider
例如:

namespace Illuminate\Hashing;use Illuminate\Support\ServiceProvider;class HashServiceProvider extends ServiceProvider
{/*** 如果延时加载,$defer 必须设置为 true 。** @var bool*/protected $defer = true;/*** Register the service provider.** @return void*/public function register(){$this->app->singleton('hash', function () {return new BcryptHasher;});}/*** Get the services provided by the provider.** @return array*/public function provides(){return ['hash'];}
}

当我们「make」时,才会注册 HashServiceProvider,即执行它的 register() 方法,进行 hash 的绑定:

class MyController extends Controller
{public function test(){// 此时才会注册 `HashServiceProvider`$hash = $this->app->make('hash');$hash->make('teststring');// 或\Hash::make('teststring');}
}

Laravel Service Provider 概念详解相关推荐

  1. SPI(Service Provider Interface)详解

    介绍 SPI 全称为 (Service Provider Interface) ,是JVM内置的一种服务提供发现机制.Java在语言层面为我们提供了一种方便地创建可扩展应用的途径.我们只需要按照SPI ...

  2. R语言生存分析(survival analysis)与生存资料有关的概念详解

    R语言生存分析(survival analysis)与生存资料有关的概念详解 目录 R语言生存分析(survival analysis)与生存资料有关的概念详解 #生存分析

  3. BlockChain:BlockChain周边概念详解+个人理解

    BlockChain:BlockChain周边概念详解+个人理解 目录 1.拜占庭将军问题 2.共识机制 1.区块链的共识机制目前有以下几种 PoW PoS DPoS 其他共识机制 1.拜占庭将军问题 ...

  4. [crypto]-02-非对称加解密RSA原理概念详解

    说明:本文使用的数据来自网络,重复的太多了,也不知道哪篇是原创. 算法原理介绍 step 说明 描述 备注 1 找出质数 P .Q - 2 计算公共模数 N = P * Q - 3 欧拉函数 φ(N) ...

  5. [crypto]-01-对称加解密AES原理概念详解

    1.对称加解密 术语:P是明文,C是密文,K是密钥,E是加密算法,D是解密算 (1).常用的对称加解密有哪些? (2).加解密的模式 [ecb]这种模式是将整个明文分成若干段相同的小段,然后对每一小段 ...

  6. @Controller,@Service,@Repository,@Component详解

    转载自 @Controller,@Service,@Repository,@Component详解 @Controller 用来表示一个web控制层bean,如SpringMvc中的控制器. @Ser ...

  7. AUTOSAR从入门到精通100讲(三十九)-AUTOSAR 通信服务-Com模块两部曲-概念详解

    Com模块概念详解 1. Com模块功能介绍 COM模块位于RTE和PDU Router模块之间. COM模块提供信号网关功能,主要的功能如下: . 为RTE提供信号导向的数据接口 . 将AUTOSA ...

  8. 容器编排技术 -- Kubernetes kubectl create service nodeport 命令详解

    容器编排技术 -- Kubernetes kubectl create service nodeport 命令详解 1 kubectl create service nodeport 2 语法 3 示 ...

  9. 容器编排技术 -- Kubernetes kubectl create service loadbalancer 命令详解

    容器编排技术 -- Kubernetes kubectl create service loadbalancer 命令详解 1 kubectl create service loadbalancer ...

最新文章

  1. 不使用任何后端代码可以开发应用程序吗?
  2. 不服来战!多伦多大学教授500美元挑战整个机器学习圈子
  3. tf.expand_dims 来增加维度
  4. golang中的socket
  5. silverlight 读取wcf服务 读取宿主端的config 良好的方法
  6. java如果把字符串转成对象_为什么Java中的字符串对象是不可变的,有什么好处?...
  7. 入门-什么是webshell?
  8. 用ASP.NET上传大文件 (转载自思归blogs)
  9. oracle的汇总模板,Oracle EBS汇总模板建立问题处理
  10. VB 源码 产生任意数之间随机数,支持负数
  11. 锐捷长ping_锐捷实战系列(二) Wireshark抓包分析Ping过程
  12. 创新设计思维总结报告
  13. [iOS] Windows 使用IPSW文件升级iOS 13 beta
  14. html的nofollow标签,详解:什么是Nofollow标签!
  15. TokenGazer评级丨TRON:BTT众筹谋求熊市破局,生态繁荣但数据受到质疑
  16. 今天准备出发去珠海横琴,去长隆海洋乐园看鲨鱼宝宝了
  17. Mac 更新系统后无法使用git
  18. 计算机浏览器应用程序,电脑打开IE浏览器显示找不到应用程序如何解决
  19. 【C语言进阶】字符函数和字符串函数
  20. xmr monero miner

热门文章

  1. 追忆那些昙花一现的P2P平台
  2. 各国文化距离——Hofstede的文化维度数据
  3. 基于FFmpeg的远程视频监控系统编解码
  4. 华为交换机配置时区_S5700系统时区不同于UTC时区导致NTP同步失败
  5. 位运算转换二进制【进制转换】
  6. 理科学计算机还是金融类,想学习金融高中应该选择文科还是理科?哪一科更适合?...
  7. 史蒂夫•鲍尔默(Microsoft)
  8. 使用Orange中的聚类算法KMeans
  9. 中国电力电气创新大会中企业家代表鲁川先生的精彩演讲震耳发聩!
  10. 记一次ansible执行报错Structure needs cleaning