instance() 将已初始化对象直接注册进容器,后续调用均返回该实例;需在 register() 中完成,确保依赖就绪,不可用于未配置或依赖未解析的对象。

在 Laravel 6 中,instance() 是服务容器提供的最直接的绑定方式:它把一个**已完全初始化的对象实例**注册进容器,后续每次 app()->make() 或类型提示注入时,都原样返回这个实例,不重新构造、不走闭包、不检查依赖。
instance 绑定的核心要求
它不是“告诉容器怎么造对象”,而是“把造好的对象塞进去”。所以关键在于:对象必须已创建完毕,且所有依赖都已就绪。
- 不能传入未完成初始化的对象(比如
new SmsService()但配置项(如env('TWILIO_SID'))还没加载,会导致运行时报错) - 不能传入依赖尚未解析的类(比如
new CacheRepository(new RedisClient()),但RedisClient本身还没被容器管理) - 推荐在服务提供者的
register()方法中调用,确保早于任何依赖解析发生
正确写法示例
假设你有一个手动配置好的日志实例:
// 在 app/Providers/AppServiceProvider.php 的 register() 方法内
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
public function register()
{
$logger = new Logger('app');
$logger->pushHandler(new StreamHandler(storage_path('logs/laravel.log')));
$this->app->instance(Logger::class, $logger);
}
之后在任意地方使用:
- 控制器构造函数中类型提示
Logger $logger→ 自动注入该实例 - 手动获取:
$log = app(Logger::class);→ 返回同一个对象
常见错误和后果
误用 instance() 容易引发运行时异常,因为容器不做校验,只负责转发:
- 传入
new HttpClient()但没设置 base_uri → 后续调用抛出 cURL 错误 - 传入
new DatabaseConnection(...)但数据库配置未加载 →Undefined index: database - 在
boot()中调用instance()→ 可能已被其他服务提前解析,导致绑定失效(尤其在队列或 Artisan 命令中)
instance 和 bind/singleton 的本质区别
三者不是“可互换的写法”,而是用途完全不同:
-
bind():每次make()都执行闭包,新建实例(适合无状态类) -
singleton():首次make()执行闭包并缓存结果,之后复用(适合连接、客户端) -
instance():不执行任何逻辑,只存取已有对象(适合外部构建、测试 Mock、全局单例对象)


















