Laravel Service Provider 概念详解
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
在「引导」过程中干了两件重要的事:
- 通过
Service Provider
的register()
方法注册「绑定」 - 所有
Servier Provider
的register()
都执行完之后,再通过它们boot()
方法,干一些别的事。
过程分析
这个「先后顺序」可以在 Laravel
的启动过程中找到:
- 首先,生成核心
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__.'/../')
);
接下来注册
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 );
然后「启动」应用。
public/index.php
:/* |-------------------------------------------------------------------------- | Run The Application |-------------------------------------------------------------------------- | */ $kernel = $app->make(Illuminate\Contracts\Http\Kernel::class); $response = $kernel->handle( $request = Illuminate\Http\Request::capture() );
由于以前的「绑定」,
$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) {//...}}
}
这个
sendRequestThroughRouter()
方法执行了一系列bootstrappers (引导器)
:// Illuminate\Foundation\Http class Kernel implements KernelContract { protected function sendRequestThroughRouter($request) {//...// 按顺序执行每个 bootstrapper$this->bootstrap();//... } }
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 概念详解相关推荐
- SPI(Service Provider Interface)详解
介绍 SPI 全称为 (Service Provider Interface) ,是JVM内置的一种服务提供发现机制.Java在语言层面为我们提供了一种方便地创建可扩展应用的途径.我们只需要按照SPI ...
- R语言生存分析(survival analysis)与生存资料有关的概念详解
R语言生存分析(survival analysis)与生存资料有关的概念详解 目录 R语言生存分析(survival analysis)与生存资料有关的概念详解 #生存分析
- BlockChain:BlockChain周边概念详解+个人理解
BlockChain:BlockChain周边概念详解+个人理解 目录 1.拜占庭将军问题 2.共识机制 1.区块链的共识机制目前有以下几种 PoW PoS DPoS 其他共识机制 1.拜占庭将军问题 ...
- [crypto]-02-非对称加解密RSA原理概念详解
说明:本文使用的数据来自网络,重复的太多了,也不知道哪篇是原创. 算法原理介绍 step 说明 描述 备注 1 找出质数 P .Q - 2 计算公共模数 N = P * Q - 3 欧拉函数 φ(N) ...
- [crypto]-01-对称加解密AES原理概念详解
1.对称加解密 术语:P是明文,C是密文,K是密钥,E是加密算法,D是解密算 (1).常用的对称加解密有哪些? (2).加解密的模式 [ecb]这种模式是将整个明文分成若干段相同的小段,然后对每一小段 ...
- @Controller,@Service,@Repository,@Component详解
转载自 @Controller,@Service,@Repository,@Component详解 @Controller 用来表示一个web控制层bean,如SpringMvc中的控制器. @Ser ...
- AUTOSAR从入门到精通100讲(三十九)-AUTOSAR 通信服务-Com模块两部曲-概念详解
Com模块概念详解 1. Com模块功能介绍 COM模块位于RTE和PDU Router模块之间. COM模块提供信号网关功能,主要的功能如下: . 为RTE提供信号导向的数据接口 . 将AUTOSA ...
- 容器编排技术 -- Kubernetes kubectl create service nodeport 命令详解
容器编排技术 -- Kubernetes kubectl create service nodeport 命令详解 1 kubectl create service nodeport 2 语法 3 示 ...
- 容器编排技术 -- Kubernetes kubectl create service loadbalancer 命令详解
容器编排技术 -- Kubernetes kubectl create service loadbalancer 命令详解 1 kubectl create service loadbalancer ...
最新文章
- 不使用任何后端代码可以开发应用程序吗?
- 不服来战!多伦多大学教授500美元挑战整个机器学习圈子
- tf.expand_dims 来增加维度
- golang中的socket
- silverlight 读取wcf服务 读取宿主端的config 良好的方法
- java如果把字符串转成对象_为什么Java中的字符串对象是不可变的,有什么好处?...
- 入门-什么是webshell?
- 用ASP.NET上传大文件 (转载自思归blogs)
- oracle的汇总模板,Oracle EBS汇总模板建立问题处理
- VB 源码 产生任意数之间随机数,支持负数
- 锐捷长ping_锐捷实战系列(二) Wireshark抓包分析Ping过程
- 创新设计思维总结报告
- [iOS] Windows 使用IPSW文件升级iOS 13 beta
- html的nofollow标签,详解:什么是Nofollow标签!
- TokenGazer评级丨TRON:BTT众筹谋求熊市破局,生态繁荣但数据受到质疑
- 今天准备出发去珠海横琴,去长隆海洋乐园看鲨鱼宝宝了
- Mac 更新系统后无法使用git
- 计算机浏览器应用程序,电脑打开IE浏览器显示找不到应用程序如何解决
- 【C语言进阶】字符函数和字符串函数
- xmr monero miner
热门文章
- 追忆那些昙花一现的P2P平台
- 各国文化距离——Hofstede的文化维度数据
- 基于FFmpeg的远程视频监控系统编解码
- 华为交换机配置时区_S5700系统时区不同于UTC时区导致NTP同步失败
- 位运算转换二进制【进制转换】
- 理科学计算机还是金融类,想学习金融高中应该选择文科还是理科?哪一科更适合?...
- 史蒂夫•鲍尔默(Microsoft)
- 使用Orange中的聚类算法KMeans
- 中国电力电气创新大会中企业家代表鲁川先生的精彩演讲震耳发聩!
- 记一次ansible执行报错Structure needs cleaning