Hyperf 3.1 DI 容器重写参数解析逻辑,基于 PHP 8.0+ 类型声明精准推断依赖,废弃反射猜名;强制要求构造函数参数带类型提示,属性注入默认启用且需#[Inject],配置统一为 PHP 数组,性能提升约15%。

Hyperf 3.1 的 DI 容器重写了构造函数参数解析逻辑
Hyperf 3.1 彻底重写了 DI 容器的参数自动解析机制,不再依赖反射参数名去匹配服务名(比如把 $logger 硬猜成 LoggerInterface),而是基于 PHP 8.0+ 的类型声明 + 属性注入能力做精准推断。这意味着你写 public function __construct(private LoggerInterface $logger),容器就能 100% 确定要注入什么,不靠注释、不靠约定。
常见错误现象:升级到 3.1 后部分服务无法注入,报 Entry "X" does not exist —— 很可能是因为旧代码里用了无类型提示的参数(如 public function __construct($db)),而新容器已放弃对这种写法的支持。
- 必须为所有构造函数参数添加明确的类型声明(接口或类)
- 支持
private/protected属性注入语法,但需配合#[Inject]或启用属性注入开关(enable_attribute_injection => true) - 移除了对
@Inject注解的运行时解析,仅保留#[Inject]Attributes 支持
属性注入(Property Injection)正式成为一等公民
在 v2.x 中属性注入是实验性功能,且需手动注册 PropertyHandler;v3.1 把它纳入核心流程,默认启用,只要加了 #[Inject] 就能生效,无需额外配置。
使用场景:适合注入“非必需依赖”或“可选辅助服务”,比如日志、监控客户端,避免污染构造函数签名。
-
#[Inject]必须写在属性上,不能写在 setter 方法上 - 属性必须是
public或protected,private不支持(PHP 8.1+ 的private readonly也不行) - 若同时存在构造函数注入和属性注入,构造函数优先执行,属性注入在其后
容器性能提升约 15%,但代价是更严格的类型约束
官方 CHANGELOG 明确提到“容器性能提升约 15%”,主要来自反射缓存优化与参数解析路径精简。但这个收益的前提是你遵守新规则:所有可被容器管理的对象,其构造函数参数必须可静态推导。
容易踩的坑:
- 动态传参(如
new Container()->get($serviceName))仍可用,但无法享受新解析逻辑的加速 - 闭包绑定(
$container->bind('foo', fn() => new Foo($container->get(Bar::class))))不会触发自动解析,必须显式调用get() - 第三方组件若仍用 v2.x 风格的
@Inject注解,会直接失效,需确认是否已发布 v3.x 兼容版本(例如hyperf/swagger3.1+ 已适配)
配置方式统一为 PHP 数组,影响容器初始化时机
v3.1 废弃 YAML 和注解式配置,全部改用 config/autoload/dependencies.php 返回数组。这不是表面变化——它让容器在框架启动早期就能完成全量服务注册,避免运行时动态加载带来的不确定性。
关键影响点:
- 原来放在
@Value注解里的配置值(如@Value("app.name"))必须改写为#[Value("app.name")],且该值必须已在dependencies.php或config/autoload/constants.php中定义 - 条件绑定(如“仅在测试环境注册 MockService”)不能再靠注解判断,得用 PHP
if (env('APP_ENV') === 'test')包裹数组项 - IDE 对
dependencies.php的类型提示支持更好,但手误少写一个return会导致整个容器初始化失败,错误信息不如 YAML 友好


















