验证下 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

浙公网安备 33010602011771号