laravel原始碼分析-佇列Queue

馬克斯MaxF發表於2022-01-07

laravel 原始碼分析具體註釋見 https://github.com/FX-Max/source-analysis-laravel

前言

佇列 (Queue) 是 laravel 中比較常用的一個功能,佇列的目的是將耗時的任務延時處理,比如傳送郵件,從而大幅度縮短 Web 請求和響應的時間。本文我們就來分析下佇列建立和執行的原始碼。

佇列任務的建立

先通過命令建立一個 Job 類,成功之後會建立如下檔案 laravel-src/laravel/app/Jobs/DemoJob.php。

> php artisan make:job DemoJob

> Job created successfully.

下面我們來分析一下 Job 類的具體生成過程。

執行 php artisan make:job DemoJob 後,會觸發呼叫如下方法。

laravel-src/laravel/vendor/laravel/framework/src/Illuminate/Foundation/Providers/ArtisanServiceProvider.php

/**
 * Register the command.
 * [A] make:job 時觸發的方法
 * @return void
 */
protected function registerJobMakeCommand()
{
    $this->app->singleton('command.job.make', function ($app) {
        return new JobMakeCommand($app['files']);
    });
}

接著我們來看下 JobMakeCommand 這個類,這個類裡面沒有過多的處理邏輯,處理方法在其父類中。

class JobMakeCommand extends GeneratorCommand

我們直接看父類中的處理方法,GeneratorCommand->handle(),以下是該方法中的主要方法。

public function handle()
{
    // 獲取類名
    $name = $this->qualifyClass($this->getNameInput());
    // 獲取檔案路徑
    $path = $this->getPath($name);
    // 建立目錄和檔案
    $this->makeDirectory($path);
    // buildClass() 通過模板獲取新類檔案的內容
    $this->files->put($path, $this->buildClass($name));
    // $this->type 在子類中定義好了,例如 JobMakeCommand 中 type = 'Job'
    $this->info($this->type.' created successfully.');
}

方法就是通過目錄和檔案,建立對應的類檔案,至於新檔案的內容,都是基於已經設定好的模板來建立的,具體的內容在 buildClass($name) 方法中。

protected function buildClass($name)
{
    // 得到類檔案模板,getStub() 在子類中有實現,具體看 JobMakeCommand 
    $stub = $this->files->get($this->getStub());
    // 用實際的name來替換模板中的內容,都是關鍵詞替換
    return $this->replaceNamespace($stub, $name)->replaceClass($stub, $name);
}

獲取模板檔案

protected function getStub()
{
    return $this->option('sync')
                    ? __DIR__.'/stubs/job.stub'
                    : __DIR__.'/stubs/job-queued.stub';
}

job.stub

<?php
/**
* job 類的生成模板
*/
namespace DummyNamespace;

use Illuminate\Bus\Queueable;
use Illuminate\Foundation\Bus\Dispatchable;

class DummyClass
{
    use Dispatchable, Queueable;

    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        //
    }
}

job-queued.stub

<?php
/**
* job 類的生成模板
*/
namespace DummyNamespace;

use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;

class DummyClass implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        //
    }
}

下面看一下前面我們建立的一個Job類,DemoJob.php,就是來源於模板 job-queued.stub。

<?php
/**
* job 類的生成模板
*/
namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;

class DemoJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        //
    }
}

至此,我們已經大致明白了佇列任務類是如何建立的了。下面我們來分析下其是如何生效執行的。

相關文章