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