文档章节

Laravel源码入门-启动引导过程(十)RegisterProviders

zhmsong
 zhmsong
发布于 2017/05/22 22:37
字数 996
阅读 45
收藏 0
点赞 0
评论 0

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

\Illuminate\Foundation\Bootstrap\RegisterProviders::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,
    ];

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

<?php

namespace Illuminate\Foundation\Bootstrap;

use Illuminate\Contracts\Foundation\Application;

class RegisterProviders
{
    /**
     * Bootstrap the given application.
     *
     * @param  \Illuminate\Contracts\Foundation\Application  $app
     * @return void
     */
    public function bootstrap(Application $app)
    {
        // 非常简单一句话,注册配置的 Providers。
        $app->registerConfiguredProviders();
    }
}

本来至此,RegisterProviders 就结束了,但再深入一步,我们看看 Application::registerConfiguredProviders() 的源代码:

//来自: Illuminate\Foundation\Application.php

   /**
     * Register all of the configured providers.
     *
     * @return void
     */
    public function registerConfiguredProviders()
    {
        // 下面是 注册配置好的 Providers 方法代码,我们注释掉改写一下。
        //(new ProviderRepository($this, new Filesystem, $this->getCachedServicesPath()))
        //            ->load($this->config['app.providers']);

        // 第一步:创建 Provider 仓库对象
        $repository = new ProviderRepository(
            $this, 
            new Filesystem, 
            $this->getCachedServicesPath()
        );
        // dump($repository);

        // 第二步:获取配置文件 config/app.php 中的 providers 数组中指定的 Providers
        // 打印出 $this($app),可以看到 $app 中的 instances 包含 config 实例
        // $this->config 是 LoadConfiguration 时 绑定的实例,原来的绑定代码如下:

        // Illuminate\Foundation\Bootstrap\LoadConfiguraton.php
        // $app->instance('config', $config = new Repository($items));

        $providers = $this->config['app.providers'];
        // dump($this);
        // dump($providers);

        // 第三步:Provider 仓库对象载入 Providers
        $repository->load($providers);
    }

==分析==

1. 第一步,从缓存服务路径(bootstrap/cache/services.php))创建仓库,为什么?深入 ProviderRepository.php 源代码可以看到,services.php 中的 服务提供者是基本的,在载入过程中,需要与 config/app.php 中的 privoders 做对比的,如果不一致,需要重新载入。La让用户添加的自己的 providers 放在 app.php 中。

2. 第二步,就是获取了所有的 config/app.php 中的 providers。

3. 第三步,载入,具体载入时,做了几件事,请看 $reponsitory->load() 源代码。

-- 比对 services.php,判定是否需要重新编译;

-- 注册事件,实际是处理 services.php 中的 when 数组,这个 when 很形象,意思是 什么时候要做什么事(件);

-- 继续注册 eager 数组中的 providers,这里 eager 急切的、热切的,是积极载入的意思,他相对的就是 lazy loading,所以 laravel 让需要先行载入的 providers 放在 eager 数组中;这里 最终实际调用了每个 provider 自己都有的 register(),纵观 Laravel 引导的全过程,实际上就是 找到列表,调用列表中每个的 register()以及必要的 boot()。

-- 最后,处理 标记为 deffered 的 providers,这其实就是 lazy loading 的内容了,这个处理只是 add,不是 register。

下面列出 services.php 大体样子,初学者根据以上描述体会吧。

<?php return array (
  'providers' => 
  array (
    0 => 'Illuminate\\Auth\\AuthServiceProvider',
    1 => 'Illuminate\\Broadcasting\\BroadcastServiceProvider',
    // 略去...2~24...
    25 => 'App\\Providers\\EventServiceProvider',
    26 => 'App\\Providers\\RouteServiceProvider',
  ),
  'eager' => 
  array (
    0 => 'Illuminate\\Auth\\AuthServiceProvider',
    1 => 'Illuminate\\Cookie\\CookieServiceProvider',
    // 略去...2~11...
    12 => 'App\\Providers\\EventServiceProvider',
    13 => 'App\\Providers\\RouteServiceProvider',
  ),
  'deferred' => 
  array (
    'Illuminate\\Broadcasting\\BroadcastManager' => 'Illuminate\\Broadcasting\\BroadcastServiceProvider',
    // 略去更多 lazy loading 的
    'validation.presence' => 'Illuminate\\Validation\\ValidationServiceProvider',
    'command.tinker' => 'Laravel\\Tinker\\TinkerServiceProvider',
  ),
  'when' => 
  array (
    'Illuminate\\Broadcasting\\BroadcastServiceProvider' => 
    array (
    ),
    'Illuminate\\Bus\\BusServiceProvider' => 
    array (
    ),
    // 略去一些事件(实际上都是空的,没写)
    'Laravel\\Tinker\\TinkerServiceProvider' => 
    array (
    ),
  ),
);

== 附录 ===

Laravel的核心思想之一是 container 和 provider,应该更精确的说是, service container 和 service provider。粗浅理解,所有的功能(路由、用户验证、缓存、数据库、分页等。。。看看 services.php )都是服务,provider 更容易的理解是 “供应商” ,这些功能都被独立成或收归到供应商那里,需要哪个服务,就把供应商叫来,叫哪里来?叫到app里,都为app提供服务,所以,Application 就是个最大的 container。我们这个供应商,其实也可以叫 vendor,只是 vendor 相对于整个框架,而 provider 还是微观一些。

 

 

 

© 著作权归作者所有

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

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

botkenni ⋅ 2016/10/28 ⋅ 0

Laravel5.3之Session源码解析(中)

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

botkenni ⋅ 2016/11/19 ⋅ 0

Laravel5.3之Session源码解析(下)

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

botkenni ⋅ 2016/11/19 ⋅ 0

Laravel 5.1 源码阅读

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

botkenni ⋅ 2016/10/09 ⋅ 0

Laravel5.2之Redis保存页面浏览量

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

botkenni ⋅ 2016/10/21 ⋅ 0

Laravel 4 入门三讲(上)laravel 在启动的时候到底做了什么?

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

成武 ⋅ 2013/11/26 ⋅ 5

Laravel5.3之Session源码解析(上)

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

botkenni ⋅ 2016/11/18 ⋅ 0

Laravel5.2队列驱动expire参数设置带来的重复执行问题 数据库驱动

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

daweilang ⋅ 2017/05/07 ⋅ 0

laravel 学习笔记——起点

本系列文章主要是方便初学 laravel 的人入门,帮一些朋友认识到如何入门、如何学习 laravel,同时补充一些忽略过的基础知识。 Laravel 给了我学习新知识的一个契机,让我更早的接触更多的东西...

xsctx7788 ⋅ 2016/10/26 ⋅ 0

Laravel框架一:原理机制篇

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

hisense20112784 ⋅ 2017/08/11 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

sbt网络问题解决方案

http://dblab.xmu.edu.cn/blog/maven-network-problem/

狐狸老侠 ⋅ 12分钟前 ⋅ 0

大数据,必须掌握的10项顶级安全技术

我们看到越来越多的数据泄漏事故、勒索软件和其他类型的网络攻击,这使得安全成为一个热门话题。 去年,企业IT面临的威胁仍然处于非常高的水平,每天都会看到媒体报道大量数据泄漏事故和攻击...

p柯西 ⋅ 55分钟前 ⋅ 0

Linux下安装配置Hadoop2.7.6

前提 安装jdk 下载 wget http://mirrors.hust.edu.cn/apache/hadoop/common/hadoop-2.7.6/hadoop-2.7.6.tar.gz 解压 配置 vim /etc/profile # 配置java环境变量 export JAVA_HOME=/opt/jdk1......

晨猫 ⋅ 今天 ⋅ 0

crontab工具介绍

crontab crontab 是一个用于设置周期性被执行的任务工具。 周期性执行的任务列表称为Cron Table crontab(选项)(参数) -e:编辑该用户的计时器设置; -l:列出该用户的计时器设置; -r:删除该...

Linux学习笔记 ⋅ 今天 ⋅ 0

深入Java多线程——Java内存模型深入(2)

5. final域的内存语义 5.1 final域的重排序规则 1.对于final域,编译器和处理器要遵守两个重排序规则: (1)在构造函数内对一个final域的写入,与随后把这个被构造对象的引用赋值给一个引用...

江左煤郎 ⋅ 今天 ⋅ 0

面试-正向代理和反向代理

面试-正向代理和反向代理 Nginx 是一个高性能的反向代理服务器,但同时也支持正向代理方式的配置。

秋日芒草 ⋅ 今天 ⋅ 0

Spring 依赖注入(DI)

1、Setter方法注入: 通过设置方法注入依赖。这种方法既简单又常用。 类中定义set()方法: public class HelloWorldOutput{ HelloWorld helloWorld; public void setHelloWorld...

霍淇滨 ⋅ 昨天 ⋅ 0

马氏距离与欧氏距离

马氏距离 马氏距离也可以定义为两个服从同一分布并且其协方差矩阵为Σ的随机变量之间的差异程度。 如果协方差矩阵为单位矩阵,那么马氏距离就简化为欧氏距离,如果协方差矩阵为对角阵,则其也...

漫步当下 ⋅ 昨天 ⋅ 0

聊聊spring cloud的RequestRateLimiterGatewayFilter

序 本文主要研究一下spring cloud的RequestRateLimiterGatewayFilter GatewayAutoConfiguration @Configuration@ConditionalOnProperty(name = "spring.cloud.gateway.enabled", matchIfMi......

go4it ⋅ 昨天 ⋅ 0

Spring clound 组件

Spring Cloud技术应用从场景上可以分为两大类:润物无声类和独挑大梁类。 润物无声,融合在每个微服务中、依赖其它组件并为其提供服务。 Ribbon,客户端负载均衡,特性有区域亲和、重试机制。...

英雄有梦没死就别停 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部