laravel 6 中单例绑定通过 singleton() 方法实现,确保服务容器仅创建一次实例并在后续解析中复用;必须在服务提供者 register() 中注册,支持接口绑定、闭包工厂和直接类名三种方式,且需通过依赖注入使用以保证生效。

在 Laravel 6 中,单例绑定就是让服务容器只创建一次实例,并在后续所有解析中复用该实例。核心方法是 singleton(),它本质是 bind($abstract, $concrete, true) 的封装,第三个参数 $shared = true 触发实例缓存行为。
怎么注册单例绑定
必须在服务提供者的 register() 方法中完成,不能放在控制器、路由或模型里:
- 接口绑定实现类(推荐):
$this->app->singleton(CacheContract::class, RedisCache::class); - 闭包工厂方式(适合需手动控制初始化逻辑):
$this->app->singleton(HttpClient::class, function ($app) {<br> return new GuzzleHttpClient(['timeout' => 5]);<br>}); - 直接绑定类名(等价于反射构造):
$this->app->singleton(Logger::class);
shared 参数不是独立方法,而是 bind 的开关
bind() 默认不共享($shared = false),但你可以显式传 true 达到和 singleton() 相同效果:
$this->app->bind(FormatterInterface::class, JsonFormatter::class, true);- 这和
$this->app->singleton(FormatterInterface::class, JsonFormatter::class);行为完全一致 - 不过官方推荐用
singleton(),语义更清晰,也避免误传false
怎么验证是否生效
单例的关键特征是「同一请求内多次获取,返回同一个对象」:
app('cache') === app('cache') // 必须为 trueapp(CacheContract::class) === app(CacheContract::class) // 同样必须为 true- 如果用
bind且没设true,结果会是false
使用时要注意什么
单例不是“用了就稳”,关键在使用场景和生命周期管理:
- 必须通过依赖注入获取,比如控制器构造函数写
public function __construct(SomeService $service),不要用app(SomeService::class)避免绕过容器机制 - FPM 模式下,单例只在单次请求内共享;Swoole 常驻内存时,单例可能跨请求存活,需主动清理状态或调用
app()->forgetInstance(SomeService::class) - 单元测试中修改了单例状态,必须手动释放,否则污染后续测试
- 闭包工厂里别做耗时操作(如查数据库),否则首次
make会阻塞整个请求











