在 laravel 框架中,门面为应用服务容器中绑定的类提供了一个“静态”接口。通常在项目开发中,我们为通过 ServiceProvider 注入容器的服务类构建一个门面,以便我们可以非常方便地调用这些类接口。并且由于门面使用了动态方法对服务容器中解析出来的对象方法调用进行了代理,我们也可以像测试注入类实例那样测试门面。今天我们就来看一下 laravel 框架中 Facade 的源码。
Facade 工作原理
在 Laravel 应用中,门面就是一个为容器中对象提供访问方式的类。该机制原理由 Facade 类实现。Laravel 自带的门面,以及我们创建的自定义门面,都会继承自 Illuminate\Support\Facades\Facade 基类。
门面类只需要实现一个方法:getFacadeAccessor
。正是 getFacadeAccessor
方法定义了从容器中解析什么。然后 Facade 基类使用魔术方法 __callStatic()
代理门面上静态方法的调用,并将其交给通过 getFacadeAccessor
方法定义的从容器中解析出来的服务类来执行。
Facade 核心源码
接下来我们来看 Facade 类的主要源码
namespace Illuminate\Support\Facades;
abstract class Facade
{
/**
* The application instance being facaded.
* Application 对象的实例
* @var \Illuminate\Contracts\Foundation\Application
*/
protected static $app;
/**
* The resolved object instances.
* 解析出来的门面对应的服务类实例。索引数组,键:门面名称;值:服务类实例
* @var array
*/
protected static $resolvedInstance;
/**
* Hotswap the underlying instance behind the facade.
* 更换当前门面对应的对象实例
* @param mixed $instance
* @return void
*/
public static function swap($instance)
{
static::$resolvedInstance[static::getFacadeAccessor()] = $instance;
static::$app->instance(static::getFacadeAccessor(), $instance);
}
/**
* Get the root object behind the facade.
* 返回当前门面对应服务对象的实例
* @return mixed
*/
public static function getFacadeRoot()
{