Loading

验证下 Facade 中静态实例变量的释放时机

验证下 Facade 中静态实例变量的释放时机

结论:

Job 中通过 Facade 创建的单例,其生命周期与 Job 一致,Job 执行完之后就释放了;

如果在 Facade 的实例中声明了一个静态的实例变量,其生命周期与队列是一致的,一直到队列停止才会释放;

<?php

namespace App\Jobs;

use App\Project\Menu\Facades\Menu;

class MenuJob extends Job
{ 
    public function handle()
    {
        \Log::info(__METHOD__ . '::' . __LINE__);
        Menu::test();
        Menu::test();
        return true;
    }
}

<?php

namespace App\Project\Menu\Facades;

use Illuminate\Support\Facades\Facade;
use App\Project\Menu\Services\MenuShareService;

/**
 * @method static void test()
 */
class Menu extends Facade
{
    public static function getFacadeAccessor()
    {
        return MenuShareService::class;
    }
}

<?php

namespace App\Project\Menu\Services;

use App\Project\Base\BaseService;

class MenuShareService
{
    public static $servicesMap = [];

    public function __construct()
    {
        \Log::info(__METHOD__ . '::' . __LINE__);
    }

    public function test()
    {
        \Log::info(__METHOD__ . '::' . __LINE__);
        if (empty(self::$servicesMap['UserMenuService'])) {
            \Log::info(__METHOD__ . '::' . __LINE__);
            self::$servicesMap['UserMenuService'] = app(UserMenuService::class);
        }
        self::$servicesMap['UserMenuService']->checkUserMenu();
    }
}

public function testJob()
{
	dispatch(new MenuJob());
	$this->assertTrue(true);
}

➜  server ✗ sudo -u www-data php artisan queue:work

   INFO  Processing jobs from the [default] queue.  

  2025-07-31 10:20:03 App\Jobs\MenuJob ................................................................................. RUNNING
  2025-07-31 10:20:03 App\Jobs\MenuJob ............................................................................. 5.56ms DONE


调用两次 Menu::test()​,MenuShareService::__construct​ 和 UserMenuService::__construct​ 各执行一次,打印的日志:

[2025-07-31 10:20:03] custom.INFO: App\Jobs\MenuJob::handle::11  
[2025-07-31 10:20:03] custom.INFO: App\Project\Menu\Services\MenuShareService::__construct::18  
[2025-07-31 10:20:03] custom.INFO: App\Project\Menu\Services\MenuShareService::test::23  
[2025-07-31 10:20:03] custom.INFO: App\Project\Menu\Services\MenuShareService::test::25  
[2025-07-31 10:20:03] custom.INFO: App\Project\Menu\Services\UserMenuService::__construct::22  
[2025-07-31 10:20:03] custom.INFO: App\Project\Menu\Services\MenuShareService::test::23  

在一个生命周期中(一次请求,或者一个 Job),Menu​ 是一个单例只创建一次,单例中的静态实例 servicesMap​ 也没有被释放。

改为触发两个 Job:

public function testJob()
{
	dispatch(new MenuJob());
	dispatch(new MenuJob());
	$this->assertTrue(true);
}

➜  server ✗ sudo -u www-data php artisan queue:work

   INFO  Processing jobs from the [default] queue.  

  2025-07-31 10:20:03 App\Jobs\MenuJob ................................................................................. RUNNING
  2025-07-31 10:20:03 App\Jobs\MenuJob ............................................................................. 5.56ms DONE
  2025-07-31 10:47:36 App\Jobs\MenuJob ................................................................................. RUNNING
  2025-07-31 10:47:36 App\Jobs\MenuJob ............................................................................. 2.00ms DONE
  2025-07-31 10:47:36 App\Jobs\MenuJob ................................................................................. RUNNING
  2025-07-31 10:47:36 App\Jobs\MenuJob ............................................................................. 1.99ms DONE

MenuShareService::__construct​ 触发两次,说明 Menu​ 单例的生命周期是在 Job 内,Job 释放之后,Menu​ 就释放了。

UserMenuService::__construct​ 没有走到,说明静态的实例变量,其生命周期是与队列一致的;

[2025-07-31 10:47:36] custom.INFO: App\Jobs\MenuJob::handle::11  
[2025-07-31 10:47:36] custom.INFO: App\Project\Menu\Services\MenuShareService::__construct::18  
[2025-07-31 10:47:36] custom.INFO: App\Project\Menu\Services\MenuShareService::test::23  
[2025-07-31 10:47:36] custom.INFO: App\Project\Menu\Services\MenuShareService::test::23  
[2025-07-31 10:47:36] custom.INFO: App\Jobs\MenuJob::handle::11  
[2025-07-31 10:47:36] custom.INFO: App\Project\Menu\Services\MenuShareService::__construct::18  
[2025-07-31 10:47:36] custom.INFO: App\Project\Menu\Services\MenuShareService::test::23  
[2025-07-31 10:47:36] custom.INFO: App\Project\Menu\Services\MenuShareService::test::23  

将队列杀掉重新启动:

➜  server ✗ sudo -u www-data php artisan queue:work

   INFO  Processing jobs from the [default] queue.  

  2025-07-31 10:52:55 App\Jobs\MenuJob ................................................................................. RUNNING
  2025-07-31 10:52:55 App\Jobs\MenuJob ............................................................................. 5.94ms DONE
  2025-07-31 10:52:55 App\Jobs\MenuJob ................................................................................. RUNNING
  2025-07-31 10:52:55 App\Jobs\MenuJob ............................................................................. 1.86ms DONE

UserMenuService::__construct​ 会触发一次:

[2025-07-31 10:52:55] custom.INFO: App\Jobs\MenuJob::handle::11  
[2025-07-31 10:52:55] custom.INFO: App\Project\Menu\Services\MenuShareService::__construct::18  
[2025-07-31 10:52:55] custom.INFO: App\Project\Menu\Services\MenuShareService::test::23  
[2025-07-31 10:52:55] custom.INFO: App\Project\Menu\Services\MenuShareService::test::25  
[2025-07-31 10:52:55] custom.INFO: App\Project\Menu\Services\UserMenuService::__construct::22  
[2025-07-31 10:52:55] custom.INFO: App\Project\Menu\Services\MenuShareService::test::23  
[2025-07-31 10:52:55] custom.INFO: App\Jobs\MenuJob::handle::11  
[2025-07-31 10:52:55] custom.INFO: App\Project\Menu\Services\MenuShareService::__construct::18  
[2025-07-31 10:52:55] custom.INFO: App\Project\Menu\Services\MenuShareService::test::23  
[2025-07-31 10:52:55] custom.INFO: App\Project\Menu\Services\MenuShareService::test::23 

posted @ 2025-07-31 11:10  zhpj  阅读(5)  评论(0)    收藏  举报