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. 机器学习之单变量线性回归(Linear Regression with One Variable)
  2. html页面获取服务器时间,[html]定时获取服务器时间和本地时间
  3. Bash Shell学习笔记一
  4. 实现链栈的各种基本运算的算法_LeetCode基础算法题第78篇:如何不用加减号实现两数的加法运算?...
  5. c语言中行号大小调整,给自己的程序加上行号
  6. CentOS 系列安装 Docker
  7. vue手势滚动_vue + any-touch实现一个iscroll 实现拖拽和滑动动画效果
  8. laravel5.5 尝试使用laravel安装器安装(失败) 最后还是用的composer。。。
  9. 百倍性能的PL/SQL优化案例(r11笔记第13天)
  10. python 微服务 etcd_python etcd api
  11. Linux终端下输出二维码
  12. LINUX命令必备技能
  13. 苹果cms V10模板|首涂第二十五套精简宽屏主题模板破解带后台无加密版
  14. 【算法动画图解】:安利一款昨天发现的app
  15. 有个码龄 10 年的程序员跟我说:“他编程从来不用鼠标”,我说:
  16. 基于51单片机的铂电阻PT100温度计proteus仿真
  17. LZMA解压缩编码算法的使用
  18. 服务器功耗计算器_无服务器在您的用例中便宜吗? 用这个计算器找出答案。
  19. Module “*” must not contain source root *. The root already belongs to module “*”
  20. 《C专家编程》之 安静的改变

热门文章

  1. 选第二大元素python(分治)
  2. PHP快递单号查询接口源码指导(快递鸟 API)
  3. redhat7.2 搭建oracle 11g RAC 问题与处理
  4. ACM的习题1178-自我记录
  5. Educoder实验五硬币抽选问题
  6. 全球名校AI课程库(32)| MIT麻省理工 · 医疗机器学习课程『Machine Learning for Healthcare』
  7. debian上硬盘休眠工具hdparm使用方法总算是弄清楚了
  8. 聚焦核心业务,降本增效
  9. 真理在缩水,还是上帝在掷骰子?
  10. hdu1222Wolf and Rabbit (公约数的巧题)