文档章节

Laravel源码入门-启动引导过程(九)RegisterFacades

zhmsong
 zhmsong
发布于 2017/05/20 00:48
字数 1537
阅读 160
收藏 4

上文介绍了 HandleExceptions,在 《Laravel源码入门-启动引导过程(五)$kernel->handle($request)》中第四个要载入的是 RegisterFacades,也就是 Foundation\Http\Kernel::bootstrapers[] 的第四个

\Illuminate\Foundation\Bootstrap\RegisterFacades::class, 如下:

// Illuminate\Foundation\Http\Kernel.php 片段

   /**
     * The bootstrap classes for the application.
     * 引导类,起引导作用的类
     *
     * @var array
     */
    protected $bootstrappers = [
        // 载入服务器环境变量(.env 文件)
        \Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class,
        // 载入配置信息(config 目录)
        \Illuminate\Foundation\Bootstrap\LoadConfiguration::class,
        // 配置如何处理异常
        \Illuminate\Foundation\Bootstrap\HandleExceptions::class,
        // 注册 Facades
        \Illuminate\Foundation\Bootstrap\RegisterFacades::class,
        // 注册 Providers
        \Illuminate\Foundation\Bootstrap\RegisterProviders::class,
        // 启动 Providers
        \Illuminate\Foundation\Bootstrap\BootProviders::class,
    ];

我们再直接贴出 RegisterFacades 类的代码,进行分析,非常直观,如下

<?php

namespace Illuminate\Foundation\Bootstrap;

use Illuminate\Foundation\AliasLoader;
use Illuminate\Support\Facades\Facade;
use Illuminate\Contracts\Foundation\Application;

class RegisterFacades
{
    /**
     * Bootstrap the given application.
     *
     * @param  \Illuminate\Contracts\Foundation\Application  $app
     * @return void
     */
    public function bootstrap(Application $app)
    {
        Facade::clearResolvedInstances();

        Facade::setFacadeApplication($app);

        AliasLoader::getInstance($app->make('config')->get('app.aliases', []))->register();
    }
}

代码虽然直观,但是对于Laravel的初学者,有个问题是难以理解它的一些概念,Facade就是其一。少于程序语言能够做这样的概念的重构,有点做博士论文的味道,以至于我们所说的Laravel的学习曲线长,主要就是因为学术味道过于浓重,无法上手就用。

来看看Facade,collins词典的解释是:The facade of a building, especially a large one, is its front wall or the wall that faces the street.用来说明建筑,那么建筑的facade是什么呢,是他的前墙面,所谓”前墙面“实际是临街的一面,很清楚了,通俗说建筑的外立面。

谷歌出来的Facade的图片大多是这里图片呈现的样子,可以看到,建筑的外立面是需要重点装饰的,以至于我们可以通过说某个建筑外面立的样子来明显定位他。下面具体说。我们来看看大家举例子时,对于facade的经典例程,如下:

 

Cache::get('akey');

先说这句代码的意思,表面看是我们一般理解的,Cache类的一个静态方法get(),返回的是通过get()获取键值为‘akey’的值。但是实际上,这里的Cache不是缓存类,get()也不是Cache类的静态方法,甚至不是Cache类的方法。那到底是什么呢?

我们接着外立面的概念,虚拟一个类吧,Illuminate\Foundation\Building,建筑物类,假如是 laravel 的 Illuminate的基础类中的一个类。再虚拟一个类,Illumniate\Supports\Facades\Building,这个不叫建筑物类了,我们把它叫做建筑物外立面类。它位于 Illuminiate支持中的 Facades中。如果说我们要写得更清晰的话,可以使用这样写:

Illuminate\Foundation\BuildingFoundation;

Illumniate\Supports\Facades\BuildingFacade;

当然因为有 namespace 的使用,我们就不用谢后缀的同义反复了。粗浅理解,我们本身有BuildingFoundation,再给建筑外面加个壳子,就成为BuildingFacade,当都建成以后,我们再去称呼他们时,往往会用 他的外壳,或者说外观的样子来做代词指代,比如 鸟巢和水立方,实际上他们是国家体育场(http://www.n-s.cn/)和国家游泳中心(www.water-cube.com/cn)的Facade。顺理成章了,当我们以 BuildFacade::get()使用时,实际上BuildFacade没有这个方法,而是调用的 BuildFoundation的get()方法。

这样做有什么好处呢,一般认为是便于可测试性与降低耦合性,说得直白一些,就像说鸟巢和水立方,比说国家体育场和国家游泳中心更方便,和更具有好的辨认性一样。更进一步,在复杂的应用容器中,对象如星空浩繁,数量庞大,大项目更是如此,如何那么容易就能提取出、表达出某个对象呢,靠传参数、传指针的方式,已经让我们搞得晕头转向,到不如,给他做个壳子(Facade)让他更好提取出来,所有耦合性也就降低了。实际上,真正的耦合性没有降低,或者说,根本不是降低了真正的业务逻辑上的耦合性,而是laravel找到一个简便有效的办法可以访问需要访问的功能或对象而已。

总结一句,BuildingFacade 更容易地解析(make())出需要的对象 BuildingFoundation。

=======

了解了 Facade,让我们再次回到具体 的 RegisterFacades 代码清单:

<?php

namespace Illuminate\Foundation\Bootstrap;

use Illuminate\Foundation\AliasLoader;
use Illuminate\Support\Facades\Facade;
use Illuminate\Contracts\Foundation\Application;

class RegisterFacades
{
    /**
     * Bootstrap the given application.
     *
     * @param  \Illuminate\Contracts\Foundation\Application  $app
     * @return void
     */
    public function bootstrap(Application $app)
    {
        // 第一步:清空所有已经解析的实例,源代码就一句:
        // static::$resolvedInstance = [];见 Illuminate\Support\Facades\Facade.php

        Facade::clearResolvedInstances();

        // 第二步:设置 $app,源代码也是一句:
        // static::$app = $app;

        Facade::setFacadeApplication($app);

        // 第三步:获取应用配置信息->获取Facade类别名->获取别名下的实例->注册实例
        // 下面是源代码,我们格式化一下,便于阅读和查看:
        // AliasLoader::getInstance($app->make('config')->get('app.aliases', []))->register();
        
        // 3.1 获取配置信息库(Illuminate\Cache\Repository.php)
        $config = $app->make('config');
        dump($config);
        
        // 3.2 获取配置库中的 app.aliases 所有Facade别名
        $aliases = $config->get('app.aliases', []);
        dump($aliases);

        // 3.3 有Facade别名获取别名实例(如果没有就创建:new static())
        $instance = AliasLoader::getInstance($aliases);
        // 查看注册前的 $instance。
        dump($instance);

        // 3.4 注册实例(看源码使用了spl_autoload_register([$this, 'load'], true, true);)
        $instances->register();
        // 查看注册后的 $instance。
        dump($instance);
    }
}

dump($config)结果:

dump($aliases)结果:所有的Facades(建筑的外立面)

注册前后dump($instance)结果:

附录:Facade的官方介绍:https://laravel.com/docs/5.4/facades

反思:说到Facade之于我们来说,就是穴位之于中医。中医不像西医,不知道也不想知道身体内的具体影像、或很细微的结构的东西,他就通过经脉,通过把脉知道病情,通过按摩具体穴位实现治愈功能。除此,Facade之于我们,也更像武林高手,点穴即可!点!点!Facade::xxx()!

反思:例子拓展:Facade都位于 Illuminate\Support\Facades\

仿造:https://laravel.com/docs/5.4/facades#facade-class-reference

Facade Class Service Container Binding 备注
NationalStadium Illuminate\Foundation\NationalStadium birdsnest http://www.n-s.cn/
NationalAquaticsCenter Illuminate\Foundation\NationalAquaticsCenter watercube http://www.water-cube.com/cn/

 

 

 

 

© 著作权归作者所有

共有 人打赏支持
zhmsong
粉丝 40
博文 126
码字总数 65130
作品 0
海淀
程序员
私信 提问
Laravel5.3之bootstrap源码解析

说明:Laravel在把Request通过送入中间件Middleware和路由Router之前,还做了程序的启动Bootstrap工作,本文主要学习相关源码,看看Laravel启动程序做了哪些具体工作,并将个人的研究心得分享...

botkenni
2016/10/28
363
0
Laravel核心解读--Console内核

Console内核 上一篇文章我们介绍了Laravel的HTTP内核,详细概述了网络请求从进入应用到应用处理完请求返回HTTP响应整个生命周期中HTTP内核是如何调动Laravel各个核心组件来完成任务的。除了处...

KevinYan
2018/12/06
0
0
Laravel5.3之Session源码解析(中)

说明:在上篇中学习了session的启动过程,主要分为两步,一是session的实例化,即IlluminateSessionStore的实例化;二是从session存储介质redis中读取的数据。Laravel5.3把session垃圾回收放...

botkenni
2016/11/19
12
0
Laravel5.3之Session源码解析(下)

说明:在中篇中学习了session的CRUD增删改查操作,本篇主要学习关闭session的相关源码。实际上,在Laravel5.3中关闭session主要包括两个过程:保存当前URL到session介质中;在Response Head...

botkenni
2016/11/19
56
0
Ruby on Rails 和 Laravel: 入门

在线web应用程序开发目前有许多正流行的框架. 也有许多不同类型的框架,比如那些拥有大量插件,可以让你更加快速的迭代 (比如 Rails),或者还有其它非常简单和低级别的 (比如 Flask). web应用...

oschina
2014/07/07
5.2K
10

没有更多内容

加载失败,请刷新页面

加载更多

发布xxl-job executor dotnet core 执行器的实现

DotXxlJob [github][https://github.com/xuanye/DotXxlJob] xxl-job的dotnet core 执行器实现,支持XXL-JOB 2.0+ 1 XXL-JOB概述 [XXL-JOB][1]是一个轻量级分布式任务调度平台,其核心设计目标...

假正经哥哥
今天
2
0
mysql 查询当天、本周,本月,上一个月的数据

今天 select * from 表名 where to_days(时间字段名) = to_days(now()); 昨天 SELECT * FROM 表名 WHERE TO_DAYS( NOW( ) ) - TO_DAYS( 时间字段名) <= 1 近7天 SELECT * FROM 表名 wher......

BraveLN
今天
3
0
Spring 事务初始化源码分析

相关文章 Spring 事务使用详解 Spring AOP 创建代理的源码解析 Spring AOP 注解方式源码解析 Spring AOP 功能使用详解 Spring 的 getBean 方法源码解析 Spring bean 创建过程源码解析 Spring...

TSMYK
今天
1
0
Android Multimedia框架总结(六)C++中MediaPlayer的C/S架构

前面几节中,都是通过java层调用到jni中,jni向下到c++层并未介绍 看下Java层一个方法在c++层 MediaPlayer后续过程 frameworks/av/media/libmedia/MediaPlayer.cpp 找一个我们之前熟悉的setDa...

天王盖地虎626
今天
3
0
【Linux】【MySQL】CentOS7安装最新版MySQL8.0.13(最新版MySQL从安装到运行)

1、前言   框框博客在线报时:2018-11-07 19:31:06   当前MySQL最新版本:8.0.13 (听说比5.7快2倍)   官方之前表示:MySQL 8.0 正式版 8.0.11 已发布,MySQL 8 要比 MySQL 5.7 快 2 ...

Code辉
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部