如何创建 Laravel 延迟加载的服务提供者
服务提供者
laravel 的服务提供者是建立在服务容器之上,实现高内聚、低耦合的功能模块。其中 register 函数负责将实现类绑定到服务容器中, boot 函数在所有服务容器注册完成之后执行,处理配置等一系列操作。
在 laravel 系统框架启动阶段,会读取配置文件 config/app.php 中 $providers 的所有需要加载的服务提供者,在所有服务提供者的 register 函数调用完成之后,再依次调用各个服务提供者的 boot 函数,完成服务提供者的注册和启动。所以不要尝试在 register 方法中注册任何监听器,路由,或者其他任何功能。否则,你可能会意外地使用到尚未加载的服务提供者提供的服务。
创建一个服务容器
创建一个接口类 和 一个对应的实现类
namespace App\Lufeijun1234\Provider\Contracts;
interface CurlContract
{
public function get($url);
public function post($url,$data,$header=[]);
}
namespace App\Lufeijun1234\Provider\Curl;
use App\Lufeijun1234\Provider\Contracts\CurlContract;
class CurlService implements CurlContract
{
public function get($url)
{
echo "get";
}
public function post($url,$data,$header=[])
{
echo "post";
}
}
执行的 artisan 命令
php artisan make:provider CurlServiceProvider
在 CurlServiceProvider 类中的 register 函数完成注册
public function register()
{
echo "curl provider register<br>";
$this->app->singleton('curl', function(){
return new CurlService;
});
}
public function boot()
{
echo "curl provider boot<br>";
}
在 config/app.php 中注册服务提供者
直接在 providers 参数中新增 App\Providers\CurlServiceProvider::class,
验证
任意注册一个空的路由,通过页面访问,可以看到刚才在 register 和 boot 中写的输出语句打印出来,说明我们的服务提供者已经被注册和启动了,在 http 控制器中,通过 \App::make('curl') 便可以访问到我们新添加的服务提供者,进行 get|post 发送请求。
延迟服务提供者
如果系统在启动时加载的提供者过多,必然会导致系统性能下降,好在 laravel 框架为我们提供延迟加载服务提供者的功能,只有真正使用到改服务提供者时,才进行绑定和启动。
延迟服务提供者需要修改的地方
class CurlServiceProvider extends ServiceProvider
{
protected $defer = true;
/**
* 中间不变的地方暂时省略
*
*/
public function provides()
{
return ['curl'];
}
}
利用框架的 artisan 命令生成缓存文件
执行 php artisan clear-compiled ,会重新生成框架缓存文件,在 bootstrap/cache/services.php 中保存系统服务提供者的所有信息,其中 deferred 保存的是所有需要延迟加载的服务提供者。
延迟加载注册启动逻辑
/**
* vendor/laravel/framework/src/Illuminate/Foundation/Application.php
* Resolve the given type from the container.
*
* (Overriding Container::make)
*
* @param string $abstract
* @param array $parameters
* @return mixed
*/
public function make($abstract, array $parameters = [])
{
$abstract = $this->getAlias($abstract);
if (isset($this->deferredServices[$abstract]) && ! isset($this->instances[$abstract])) {
$this->loadDeferredProvider($abstract);
}
return parent::make($abstract, $parameters);
}
上边代码是系统服务容器解析实现类的逻辑,中间有一层判断,如果待解析的类在延迟加载服务提供者列表中,并且是首次解析时,便会调用延迟加载函数 loadDeferredProvider , 调用服务提供者的 register 和 boot 函数进行注册和绑定。之后在进行后续解析。
小结
通过对 laravel 框架服务提供者逻辑的理解,手动创建一个发送请求的 CurlServiceProvider 服务提供者,并且实现延迟加载,降低对框架系统性能的影响。如有不对,还请指教
本作品采用《CC 协议》,转载必须注明作者和本文链接