Symfony 4 中非共享服务通过设置 shared: false 实现,每次获取均创建新实例,适用于 DTO 构建器等无状态场景;其不参与单例管理,依赖传递时需注意生命周期一致性。

在 Symfony 4 中,服务默认是共享的(shared),即容器每次注入或获取该服务时,返回的是同一个实例。但某些场景下——比如需要每次获取一个干净、无状态的新对象(如 DTO 构建器、临时上下文、测试用模拟器)——你得显式关闭共享行为。
如何定义一个非共享服务
在 config/services.yaml 中,为对应服务添加 shared: false 配置即可:
- 使用类名自动注册方式(推荐):
# config/services.yaml
# 自动注册 src/Service/ 下所有类
# 但对特定类禁用共享
services:
App\Service\TemporaryContext:
shared: false
- 若用工厂方式定义,同样加 shared: false:
App\Service\ReportGenerator:
factory: ['@App\Service\ReportFactory', 'create']
shared: false
非共享服务的实际影响
一旦设为 shared: false,每次调用 $container->get(ReportGenerator::class) 或通过构造函数注入,都会触发一次全新实例化(包括重新执行构造逻辑和依赖解析)。
- 不会复用已创建的实例,即使在同一请求生命周期内多次获取
- 不参与容器的“单例生命周期管理”,例如不会被
kernel.reset事件重置 - 无法被其他服务以
public: true+autowire: true的方式直接缓存引用(因为本身不共享)
共享与非共享服务共存时的注意事项
混合使用时需留意依赖传递性:
- 如果 A 服务是 shared: true,且它依赖 B 服务(shared: false),那么每次 A 调用 B 的方法时,B 总是新实例 —— 但 A 自身仍是单例,这点要明确
- 避免在非共享服务中持有跨请求的状态(如静态属性、全局变量),否则会引发不可预测的副作用
- 性能敏感路径慎用非共享:频繁 new 实例 + autowire 解析可能带来微小开销,一般可忽略,但高频调用处建议压测确认


















