短生命周期对象必须用make()而非get():make()每次新建实例且不缓存,适用于request dto等临时对象;get()默认返回单例缓存实例,无法满足按需重建需求。

短生命周期对象必须用 make() 而不是 get()
Hyperf 的 DI 容器默认返回单例(Singleton),get() 每次取的都是同一个实例。如果你需要每次调用都新建对象(比如 Request DTO、临时计算上下文、一次性的命令封装体),必须改用 make() —— 它绕过容器的实例缓存,强制构造新对象。
-
make(YourClass::class):总是 new 一个新实例,不注册进容器,不参与生命周期管理 -
get(YourClass::class):首次调用才 new,后续全走缓存,等同于 singleton - 即使你在
@Inject属性上标注了类,Hyperf 仍会按容器绑定类型决定是否复用——所以注解本身不改变生命周期
需要手动传参时,make() 支持数组参数或闭包解析
如果短生命周期对象的构造函数依赖运行时参数(比如 new OrderItem($orderId, $quantity)),不能靠配置绑定解决,得在调用时传入:
- 最常用:
make(OrderItem::class, ['orderId' => 123, 'quantity' => 2]) - 更灵活(尤其含接口依赖):
make(OrderItem::class, function (ContainerInterface $container) use ($orderId, $quantity) { return new OrderItem($orderId, $quantity, $container->get(PriceCalculator::class)); }) - 注意:参数键名必须和构造函数参数名完全一致(PHP 8+ 支持命名参数可省略键名,但 Hyperf 2.x/3.x 默认仍依赖顺序或显式键名)
别在 @Inject 里指望短生命周期
@Inject 是编译期注入,绑定发生在容器初始化阶段,它背后调用的是 get()。哪怕你把类绑定为 Container::SINGLETON = false,Hyperf 也不会因此对 @Inject 属性做每次重建——这是设计使然,不是 bug。
- 错误写法:
#[Inject] public OrderItem $item;
→ 永远是同一个实例 - 正确做法:在方法内按需
make(),或把对象创建逻辑封装进工厂方法 - 若高频创建,建议加个简单工厂类,避免到处写重复的
make()调用
性能与内存要注意:短生命周期 ≠ 随意 new
频繁 make() 大对象(比如带大量依赖、初始化开销大的类),会绕过容器优化,可能引发 GC 压力或构造耗时上升。
- 确认真的需要“每次全新”:DTO、VO、临时聚合对象通常没问题;Service、Client、Repository 类一般不该这么用
- 留意构造函数里是否做了阻塞操作(如 DB 查询、HTTP 调用)——短生命周期对象不该承担这些职责
- Hyperf 3.1+ 对
make()做了轻量缓存(仅限无参构造),但带参调用仍无缓存,这点和 Laravel 的makeWith()行为不同
make() 还是 get()。很多人卡在以为改个注解或加个标签就能切换,其实根本没走到那一步。











