文档章节

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

zhmsong
 zhmsong
发布于 2017/05/20 00:48
字数 1537
阅读 153
收藏 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
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
Laravel核心代码学习--HTTP内核

Http Kernel Http Kernel是Laravel中用来串联框架的各个核心组件来网络请求的,简单的说只要是通过来启动框架的都会用到Http Kernel,而另外的类似通过命令、计划任务、队列启动框架进行处理...

kevinyan
11/15
0
0
Laravel框架一:原理机制篇

http://www.cnblogs.com/XiongMaoMengNan/p/6644892.html Laravel作为在国内国外都颇为流行的PHP框架,风格优雅,其拥有自己的一些特点。 一. 请求周期   Laravel 采用了单一入口模式,应用...

hisense20112784
2017/08/11
0
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周日乱弹 —— 懒床是对冬天最起码的尊重

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @瘟神灬念 :分享daniwellP/桃音モモ的单曲《Nyan Cat》 《Nyan Cat》- daniwellP/桃音モモ 手机党少年们想听歌,请使劲儿戳(这里) @巴拉迪...

小小编辑
今天
27
2
码云项目100,水一发

简单回顾一下: 早期构想最多的,是希望能将PHP一些类和编码分区做得更细,所以很多尝试。但不得不说,PHP的功能过于单一,是的,也许写C/C++扩展,可以解决问题,那我为什么不用C#或者Golan...

曾建凯
今天
4
0
Spring应用学习——AOP

1. AOP 1. AOP:即面向切面编程,采用横向抽取机制,取代了传统的继承体系的重复代码问题,如下图所示,性能监控、日志记录等代码围绕业务逻辑代码,而这部分代码是一个高度重复的代码,也就...

江左煤郎
今天
4
0
eclipse的版本

Eclipse各版本代号一览表 Eclipse的设计思想是:一切皆插件。Eclipse核心很小,其它所有功能都以插件的形式附加于Eclipse核心之上。 Eclipse基本内核包括:图形API(SWT/Jface),Java开发环...

mdoo
今天
3
0
SpringBoot源码:启动过程分析(一)

本文主要分析 SpringBoot 的启动过程。 SpringBoot的版本为:2.1.0 release,最新版本。 一.时序图 还是老套路,先把分析过程的时序图摆出来:时序图-SpringBoot2.10启动分析 二.源码分析 首...

Jacktanger
今天
12
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部