文档章节

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

zhmsong
 zhmsong
发布于 2017/05/20 00:48
字数 1537
阅读 141
收藏 4
点赞 0
评论 0

上文介绍了 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
粉丝 41
博文 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 5.1 源码阅读

安装,和创建项目,都是通过Composer,简单,略过。 Entry && Kernel 网站入口文件,${Laravel-project}/public/index.PHP: 生成Request,处理Request(),生成Response,发送Resonse。常规...

botkenni
2016/10/09
25
0
Laravel5.2之Redis保存页面浏览量

说明:本文主要讲述使用Redis作为缓存加快页面访问速度。同时,会将开发过程中的一些截图和代码黏上去,提高阅读效率。 备注:最近在学习github上别人的源码时,发现好多在计算一篇博客页面访...

botkenni
2016/10/21
16
0
Laravel框架一:原理机制篇

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

hisense20112784
2017/08/11
0
0
Laravel 4 入门三讲(上)laravel 在启动的时候到底做了什么?

  在 Laravel 4 的官方文档里介绍了如何快速的使用它来开始程序的开发。然而相对于如何快速的输出“Hello Word!”笔者更关心的,是在执行到“Hello Word!”这句代码之前程序都做了哪些事情...

成武
2013/11/26
0
5
Laravel5.3之Session源码解析(上)

说明:本文主要通过学习Laravel的session源码学习Laravel是如何设计session的,将自己的学习心得分享出来,希望对别人有所帮助。Laravel在中定义了session中间件,并通过该中间件来设计sessi...

botkenni
2016/11/18
13
0
开源IOT--最小物联网系统

文档 一步步搭建物联网系统 HTTP vs CoAP 现有的这个版本是HTTP版,目前的CoAP版正在开发中,欢迎加入。 https://github.com/phodal/iot-coap Minimum Internet of Things A Minimum IOT wi...

Phodal
2013/12/24
14.9K
1
Laravel5.2队列驱动expire参数设置带来的重复执行问题 数据库驱动

'connections' => [ .... 'database' => [ 'driver' => 'database', 'table' => 'jobs', 'queue' => 'default', 'expire' => 60, ], 'redis' => [ 'driver' => 'redis',......

daweilang
2017/05/07
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

about git flow

  昨天元芳做了git分支管理规范的分享,为了拓展大家关于git分支的认知,这里我特意再分享这两个关于git flow的链接,大家可以看一下。 Git 工作流程 Git分支管理策略   git flow本质上是...

qwfys
今天
2
0
Linux系统日志文件

/var/log/messages linux系统总日志 /etc/logrotate.conf 日志切割配置文件 参考https://my.oschina.net/u/2000675/blog/908189 dmesg命令 dmesg’命令显示linux内核的环形缓冲区信息,我们可...

chencheng-linux
今天
1
0
MacOS下给树莓派安装Raspbian系统

下载镜像 前往 树莓派官网 下载镜像。 点击 最新版Raspbian 下载最新版镜像。 下载后请,通过 访达 双击解压,或通过 unzip 命令解压。 检查下载的文件 ls -lh -rw-r--r-- 1 dingdayu s...

dingdayu
今天
1
0
spring boot使用通用mapper(tk.mapper) ,id自增和回显等问题

最近项目使用到tk.mapper设置id自增,数据库是mysql。在使用通用mapper主键生成过程中有一些问题,在总结一下。 1、UUID生成方式-字符串主键 在主键上增加注解 @Id @GeneratedValue...

北岩
今天
2
0
告警系统邮件引擎、运行告警系统

告警系统邮件引擎 cd mail vim mail.py #!/usr/bin/env python#-*- coding: UTF-8 -*-import os,sysreload(sys)sys.setdefaultencoding('utf8')import getoptimport smtplibfr......

Zhouliang6
今天
1
0
Java工具类—随机数

Java中常用的生成随机数有Math.random()方法及java.util.Random类.但他们生成的随机数都是伪随机的. Math.radom()方法 在jdk1.8的Math类中可以看到,Math.random()方法实际上就是调用Random类...

PrivateO2
今天
2
0
关于java内存模型、并发编程的好文

Java并发编程:volatile关键字解析    volatile这个关键字可能很多朋友都听说过,或许也都用过。在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果。在...

DannyCoder
昨天
1
0
dubbo @Reference retries 重试次数 一个坑

在代码一中设置 成retries=0,也就是调用超时不用重试,结果DEBUG的时候总是重试,不是0吗,0就不用重试啊。为什么还是调用了多次呢? 结果在网上看到 这篇文章才明白 https://www.cnblogs....

奋斗的小牛
昨天
2
0
数据结构与算法3

要抓紧喽~~~~~~~放羊的孩纸回来喽 LowArray类和LowArrayApp类 程序将一个普通的Java数组封装在LowArray类中。类中的数组隐藏了起来,它是私有的,所以只有类自己的方法才能访问他。 LowArray...

沉迷于编程的小菜菜
昨天
1
0
spring boot应用测试框架介绍

一、spring boot应用测试存在的问题 官方提供的测试框架spring-boot-test-starter,虽然提供了很多功能(junit、spring test、assertj、hamcrest、mockito、jsonassert、jsonpath),但是在数...

yangjianzhou
昨天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部