跳转到主要内容

什么是服务容器

Laravel 的服务容器是用来管理类依赖并进行依赖注入的机制。所谓依赖注入,指的是通过构造器或(在某些情况下)setter 方法,将类所需的依赖「注入」到类中。 来看下面的示例:
此示例中,PodcastController 需要从 Apple Music 等数据源获取 Podcast。因此我们将能够获取 Podcast 的服务注入给它。这样一来,在测试时就可以很方便地替换 AppleMusic 服务的 mock(假实现)。
深入理解服务容器对于构建大型 Laravel 应用不可或缺,也有助于为 Laravel 核心贡献代码。

零配置解析

如果类只依赖其他具体类(而不是接口),就无需告诉容器如何解析它。例如你在 routes/web.php 中写下这段代码:
这个例子把类定义在路由文件内只是为了演示。真实应用中,服务类请放到 app/Services 目录下。
访问该路由时,Laravel 会自动解析 Service 类并注入到路由处理器中。你无需任何配置就能享受依赖注入。 Laravel 应用中编写的许多类(控制器、事件监听器、中间件等)都会通过容器自动注入依赖。

绑定

基本绑定

大部分绑定都会在服务提供者中注册。在服务提供者中可以通过 $this->app 属性访问容器。

bind

bind 方法把类或接口名与一个闭包组合,注册为绑定。
闭包会接收容器本身作为参数,可以用它解析子依赖。 如果想在服务提供者之外操作容器,请使用 App 门面。
不依赖接口的类无需向容器注册绑定。容器可以通过反射自动解析这类对象。

singleton

singleton 方法会让某个类或接口只解析一次。解析出来的单例,后续对容器的调用都会返回同一实例。

instance

也可以通过 instance 方法把已有的对象实例绑定到容器上。之后对该绑定的解析都会返回该实例。

将接口绑定到实现

服务容器的一个强大功能是可以把接口绑定到特定实现。以 EventPusher 接口与 RedisEventPusher 实现为例:
之后,容器就会给需要 EventPusher 实现的类注入 RedisEventPusher。你只需在构造器中类型提示 EventPusher 接口即可。
依赖接口后,即使替换实现也无需修改代码,测试和未来的更改都更方便。

自动解析(通过类型提示进行 DI)

服务容器在解析控制器、事件监听器、中间件等类时,会读取构造器的类型提示并自动注入依赖。
只要 UserRepository 不依赖接口,就无需向容器注册。当访问对应路由时,容器会自动解析依赖并注入控制器。

从容器解析

make 方法

使用 make 方法可以从容器中解析类实例。
若某个依赖无法被容器解析,可以使用 makeWith 方法额外传入参数。

自动注入

实际开发中很少直接调用 make。只要在容器负责解析的类(控制器、事件监听器、中间件等)的构造器上加上类型提示,容器就会自动注入依赖。

门面与容器的关系

Laravel 的门面为容器中的对象提供了静态接口。例如,Cache::get() 在内部会从容器获取 Cache 服务并调用。
门面是容器的便捷包装。测试时也可以把门面替换成 mock。

构造器注入实战示例

来看实际应用中一种典型模式。
1

定义接口

2

创建实现类

3

在服务提供者中绑定

4

在控制器中接收注入

采用这种模式后,即使把支付服务从 Stripe 换成其他供应商,也只需修改一处绑定。

下一步

服务提供者

学习如何通过服务提供者注册绑定。
最后修改于 2026年7月18日