Laravel源码解析--看看Lumen到底比Laravel轻在哪里

在前面一篇《Laravel源码解析--Laravel生命周期详解》中我们利用xdebug详细了解了下Laravel一次请求中到底做了哪些处理。今天我们跟 Lumen 对比下,看看 Lumen 比 Laravel 轻在哪里?

1、Lumen生命周期

相比于Laravel,在Lumen中,你对框架有着更多的控制权。Lumen的入口文件相比于Laravel要简单许多。

<?php

/*
|--------------------------------------------------------------------------
| Create The Application
|--------------------------------------------------------------------------
|
| First we need to get an application instance. This creates an instance
| of the application / container and bootstraps the application so it
| is ready to receive HTTP / Console requests from the environment.
|
*/

$app = require __DIR__.‘/../bootstrap/app.php‘;

/*
|--------------------------------------------------------------------------
| Run The Application
|--------------------------------------------------------------------------
|
| Once we have the application, we can handle the incoming request
| through the kernel, and send the associated response back to
| the client‘s browser allowing them to enjoy the creative
| and wonderful application we have prepared for them.
|
*/

$app->run();

同样的,我们先看下 bootstrap/app.php 文件。

// 1、毫无疑问,首先加载自动加载
require_once __DIR__.‘/../vendor/autoload.php‘;

// 2、将根目录下的.env文件中的配置加载到$_ENV、$_SERVER和putfile()中,对Laravel生命周期有印象的应该还记得
// Laravel中是在$bootstrappers数组中,先加载.ENV文件,然后再加载config/*.php里的所有配置文件。
// 而在Lumen中,默认只加载了.ENV中的文件,你可以将所有的配置信息都写在.ENV文件中,然后在项目中可以用env()方法获取。
// 当然,你也可以像Laravel那样,将所有的配置信息放到config/*.php下面,不过这需要你在获取$app实例后手动调用$app->configure(‘api‘);方法。
// 这里就是Lumen比Laravel轻的一个地方,但我感觉只使用.ENV文件或config配置都不太合理,还是两个配合使用最为方便。所以这里Lumen就不会比Laravel轻了。
try {
    (new Dotenv\Dotenv(dirname(__DIR__)))->load();
} catch (Dotenv\Exception\InvalidPathException $e) {
    //
}

/*
|--------------------------------------------------------------------------
| Create The Application
|--------------------------------------------------------------------------
|
| Here we will load the environment and create the application instance
| that serves as the central piece of this framework. We‘ll use this
| application as an "IoC" container and router for this framework.
|
*/
// 3、创建Lumen App实例
$app = new Laravel\Lumen\Application(
    dirname(__DIR__)
);

创建Lumen实例的时候,肯定也做了一些初始化工作。

/**
     * Create a new Lumen application instance.
     *
     * @param  string|null  $basePath
     * @return void
     */
    public function __construct($basePath = null)
    {     // 设置时区
        if (! empty(env(‘APP_TIMEZONE‘))) {
            date_default_timezone_set(env(‘APP_TIMEZONE‘, ‘UTC‘));
        }
     // 设置路径
        $this->basePath = $basePath;
      // 向容器中的instances中绑定app,path,env,config等,并绑定一些aliases
        $this->bootstrapContainer();     // 注册错误处理
        $this->registerErrorHandling();     // 向容器中注入Router
        $this->bootstrapRouter();
    }

相比Laravel,Lumen做的初始化工作要少很多--包自动发现、路径的注册、一些基础服务提供者的注册、注册aliases时也少了很多。得到App实例后,让我们继续回头看 bootstraps/app.php 中去。

// 3、创建Lumen App实例
$app = new Laravel\Lumen\Application(
    dirname(__DIR__)
);

// 4、如果你需要在应用中使用门面方法,则取消此行注释
// $app->withFacades();

// 5、如果你想要在应用中使用Eloquent,则取消此行注释
// $app->withEloquent();

/*
|--------------------------------------------------------------------------
| Register Container Bindings
|--------------------------------------------------------------------------
|
| Now we will register a few bindings in the service container. We will
| register the exception handler and the console kernel. You may add
| your own bindings here if you like or you can make another file.
|
*/
// 6、注册容器绑定,绑定异常处理类的实现和Console的实现。
// 相比Laravel,Lumen少绑定了一个Http\Kernel的实现
$app->singleton(
    Illuminate\Contracts\Debug\ExceptionHandler::class,
    App\Exceptions\Handler::class
);

$app->singleton(
    Illuminate\Contracts\Console\Kernel::class,
    App\Console\Kernel::class
);

/*
|--------------------------------------------------------------------------
| Register Middleware
|--------------------------------------------------------------------------
|
| Next, we will register the middleware with the application. These can
| be global middleware that run before and after each request into a
| route or middleware that‘ll be assigned to some specific routes.
|
*/

// 7、每个request都需要通过的一个中间件组,相比Laravel,少了一些固定要走的中间件,那么如果你把Laravel中固定的中间件注释掉,是不是就一样了呢?
// $app->middleware([
//     App\Http\Middleware\ExampleMiddleware::class
// ]);

// 8、注册路由中间件,同样在Laravel中,也默认定义了很多路由中间件
// $app->routeMiddleware([
//     ‘auth‘ => App\Http\Middleware\Authenticate::class,
// ]);

/*
|--------------------------------------------------------------------------
| Register Service Providers
|--------------------------------------------------------------------------
|
| Here we will register all of the application‘s service providers which
| are used to bind services into the container. Service providers are
| totally optional, so you are not required to uncomment this line.
|
*/

// 9、按需注册服务提供者,而在Laravel中,除了注册了几个基础的服务提供在,还会注册config/app.php中providers数组里所有的服务提供者。
// 还是那句话,如果你把config/app.php中providers数组中都注释掉呢?对了,在Laravel5.5引入包自动发现后,它还会注册bootstrap/cache/packages.php中的服务提供者
 $app->register(App\Providers\AppServiceProvider::class);
 $app->register(App\Providers\AuthServiceProvider::class);
 $app->register(App\Providers\EventServiceProvider::class);

/*
|--------------------------------------------------------------------------
| Load The Application Routes
|--------------------------------------------------------------------------
|
| Next we will include the routes file so that they can all be added to
| the application. This will provide all of the URLs the application
| can respond to, as well as the controllers that may handle them.
|
*/
// 10、注册路由
$app->router->group([
    ‘namespace‘ => ‘App\Http\Controllers‘,
], function ($router) {
    require __DIR__.‘/../routes/web.php‘;
});

// 11、返回App实例
return $app;

到这里,整个Lumen应用已经初始化完毕。之后 $app->run(); 其实就是根据之前注册的路由(执行每个服务提供者的boot()方法,也在这个方法中),然后进行路由分发。这与Laravel并没有什么太大区别。

综上所述,我们总结一下Lumen应用比Laravel在哪些方面轻了。

  1. 关于.ENV文件和config配置文件的加载,但实际上更建议将Lumen的与Laravel的保持一致
  2. 在new App实例的时候,Lumen所做的初始化工作,比Laravel少了一些,例如,包自动发现,路径的注册,基本服务提供者和一些aliases等。
  3. 关于request需要通过默认中间件。但其实我觉得有些还是必要的,比如\App\Http\Middleware\CheckForMaintenanceMode::class, 和\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, 等。
  4. 我个人认为应该是相比与Laravel,耗时最多的一个,就是对各种服务提供者的注册和引导(执行boot()方法)。

下面做个测试,当不对Laravel做任何处理的时候,看看启动需要多久?

Route::get(‘/‘, function () {
    $end = microtime(true);
    return $end - LARAVEL_START;
//    return view(‘welcome‘);
});

差不多是在 0.16353797912598 秒左右。而Lumen在开启一些基本的服务后的启动时间为 0.043106079101562 ,与Laravel相差了将近有4倍。相当于光启动框架,任何逻辑处理都还没开始,Laravel比Lumen多耗时0.12s。如果我们利用一些Laravel的性能优化策略,比如缓存配置文件等会稍稍减少Laravel的启动时间 0.12118005752563 。因为php的特性,每一个request,都需要将之前的所有动作执行一遍,所以App的启动还是一个比较耗时的任务。

这时候我就想安利一下颠覆php的拓展--swoole。下一章会讲解给Laravel插上翅膀的一个用swoole做的composer包。

原文地址:https://www.cnblogs.com/johnson108178/p/10069240.html

时间: 2024-10-01 06:19:34

Laravel源码解析--看看Lumen到底比Laravel轻在哪里的相关文章

Laravel框架下路由的使用(源码解析)

本篇文章给大家带来的内容是关于Laravel框架下路由的使用(源码解析),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 前言 我的解析文章并非深层次多领域的解析攻略.但是参考着开发文档看此类文章会让你在日常开发中更上一层楼. 废话不多说,我们开始本章的讲解. 入口 Laravel启动后,会先加载服务提供者.中间件等组件,在查找路由之前因为我们使用的是门面,所以先要查到Route的实体类. 注册 第一步当然还是通过服务提供者,因为这是laravel启动的关键,在 RouteSer

Laravel源码分析--Laravel生命周期详解

一.XDEBUG调试 这里我们需要用到php的 xdebug 拓展,所以需要小伙伴们自己去装一下,因为我这里用的是docker,所以就简单介绍下在docker中使用xdebug的注意点. 1.在phpstorm中的 Perferences >> Languages & Framework >> PHP >> debug >> DBGp Proxy 中的Host填写的是宿主机的IP地址.可以在命令行中使用ifconfig / ipconfig查看你的本

源码解析:dialog, popupwindow, 和activity 的第一个view是怎么来的?

问题 在慢慢熟悉android 的过程中,发现一个view 或者layout的初始化,或者构造的流程还是比较清楚的,也就是加到父控件中,然后就开始了对应的生命周期.但是整个界面的父控件,或者说系统的第一个view, 是怎么来的,如何初始化和绘制的呢? 概述 概述:带着困扰我的问题,在前文的基础上,继续分析应用界面和framework的关系,通过分析viewrootimpl 的来源,并结合dialog, popupwindow, 和activity 的 根view的创建流程,回答了问题界面的根vi

【转】Java 集合系列12之 TreeMap详细介绍(源码解析)和使用示例

概要 这一章,我们对TreeMap进行学习.我们先对TreeMap有个整体认识,然后再学习它的源码,最后再通过实例来学会使用TreeMap.内容包括:第1部分 TreeMap介绍第2部分 TreeMap数据结构第3部分 TreeMap源码解析(基于JDK1.6.0_45)第4部分 TreeMap遍历方式第5部分 TreeMap示例 转载请注明出处:http://www.cnblogs.com/skywang12345/admin/EditPosts.aspx?postid=3310928 第1部

Spring IoC源码解析——Bean的创建和初始化

Spring介绍 Spring(http://spring.io/)是一个轻量级的Java 开发框架,同时也是轻量级的IoC和AOP的容器框架,主要是针对JavaBean的生命周期进行管理的轻量级容器,可以单独使用,也可以和Struts框架,MyBatis框架等组合使用. IoC介绍 IoC是什么 Ioc-Inversion of Control,即"控制反转",不是什么技术,而是一种设计思想.在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控

给jdk写注释系列之jdk1.6容器(2)-LinkedList源码解析

LinkedList是基于链表结构的一种List,在分析LinkedList源码前有必要对链表结构进行说明. 1.链表的概念 链表是由一系列非连续的节点组成的存储结构,简单分下类的话,链表又分为单向链表和双向链表,而单向/双向链表又可以分为循环链表和非循环链表,下面简单就这四种链表进行图解说明.           1.1.单向链表 单向链表就是通过每个结点的指针指向下一个结点从而链接起来的结构,最后一个节点的next指向null.      1. 2.单向循环链表           单向循环

EventBus3.0源码解析

本文主要介绍EventBus3.0的源码 EventBus是一个Android事件发布/订阅框架,通过解耦发布者和订阅者简化 Android 事件传递. EventBus使用简单,并将事件发布和订阅充分解耦,从而使代码更简洁. 本文主要从以下几个模块来介绍 1.EventBus使用 2.EventBus注册源码解析 3.EventBus事件分发解析 4.EventBus取消注册解析 一.EventBus使用 1.首先是注册 EventBus.getDefault().register(this)

Python2 基本数据结构源码解析

Python2 基本数据结构源码解析 Contents 0x00. Preface 0x01. PyObject 0x01. PyIntObject 0x02. PyFloatObject 0x04. PyStringObject 0x05. PyListObject 0x06. PyDictObject 0x07. PyLongObject 0x00. Preface 一切皆对象,这是Python很重要的一个思想之一,虽然在语法解析上有些细节还是不够完全对象化,但在底层源码里,这个思想还是贯穿

ArrayList源码解析

ArrayList源码解析 ArrayList简介: ArrayList 是list接口的一个常用实现类.它的对象可以认为是一维数组的"类版本".我们很快就可以看到,ArrayList 对象可以看做是一维数组的改良版本.类似于数组,ArrayList 对象支持元素的随机访问:也就是说,只要给出元素的索引,任何元素的访问时间都是常数.但是同数组不同的是,ArrayList 对象的大小在程序执行的过程中可以自动进行调整,并且ArrayList对象具有在任何索引位置插入和删除对象的方法,而数