服务提供器是所有 Laravel 应用程序引导中心。你的应用程序自定义的服务、第三方资源包提供的服务以及 Laravel 的所有核心服务都是通过服务提供器进行注册(register)和引导(boot)的。
拿一个Laravel框架自带的服务提供器来举例子
class BroadcastServiceProvider extends ServiceProvider
{
protected $defer = true;
public function register()
{
$this->app->singleton(BroadcastManager::class, function ($app) {
return new BroadcastManager($app);
});
$this->app->singleton(BroadcasterContract::class, function ($app) {
return $app->make(BroadcastManager::class)->connection();
});
//将BroadcastingFactory::class设置为BroadcastManager::class的别名
$this->app->alias(
BroadcastManager::class, BroadcastingFactory::class
);
}
public function provides()
{
return [
BroadcastManager::class,
BroadcastingFactory::class,
BroadcasterContract::class,
];
}
}
在服务提供器BroadcastServiceProvider
的register
中, 为BroadcastingFactory
的类名绑定了类实现BroadcastManager,这样就能通过服务容器来make出通过BroadcastingFactory::class
绑定的服务BroadcastManger
对象供应用程序使用了。
首先laravel注册和引导应用需要的服务是发生在寻找路由处理客户端请求之前的Bootstrap阶段的,在框架的入口文件里我们可以看到,框架在实例化了Application
对象后从服务容器中解析出了HTTP Kernel
对象
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
$response = $kernel->handle(
$request = Illuminate\Http\Request::capture()
);
在Kernel处理请求时会先让请求通过中间件然后在发送请求给路由对应的控制器方法, 在这之前有一个BootStrap阶段通过执行下面列出的框架预定义脚手架的bootstrap方法来引导启动应用程序的各个部分从而完成Laravel应用程序的引导
1. DetectEnvironment 检查环境
2. LoadConfiguration 加载应用配置
3. ConfigureLogging 配置日至
4. HandleException 注册异常处理的Handler
5. RegisterFacades 注册Facades
6. RegisterProviders 注册Providers
7. BootProviders 启动Providers
namespace Illuminate\Foundation;
class Application extends Container implements ...
{
public function bootstrapWith(array $bootstrappers)
{
$this->hasBeenBootstrapped = true;
foreach ($bootstrappers as $bootstrapper) {
$this['events']->fire('bootstrapping: '.$bootstrapper, [$this]);
$this->make($bootstrapper)->bootstrap($this);
$this['events']->fire('bootstrapped: '.$bootstrapper, [$this]);
}
}
}
再第6和第7个框架的引导程序中会进行服务提供其的注册和初始化,关于注册又分为即时注册和延迟注册,延迟注册让我们在真正需要解析服务前或者时某个事件发生后再来执行服务提供器的注册方法,避免在框架一开始阶段就注册大量某些场景才会用到的服务浪费资源和时间。 如果我们想使用服务容器解析自己定义或者第三方软件包的服务就需要通过服务提供器里使用服务容器的singleton、bind、alias方法注册到服务容器中去,这样才能用服务容器make解析出服务或者时直接用门面来访问服务里提供的方法。 大家可以点击“阅读原文” 阅读关于Laravel服务提供器的源码分析。