annotationcollector::getclassesbyannotation 返回空数组主因是调用过早,注解扫描尚未完成;需确保在 onworkerstart 或命令行 handle() 中调用,且注解类位于扫描路径、正确声明 @annotation 并继承 abstractannotation。

AnnotationCollector::getClassesByAnnotation 返回空数组?
多数时候不是注解没写对,而是 AnnotationCollector 还没完成扫描 —— Hyperf 的注解收集发生在容器启动的「扫描阶段」,早于你手动调用的位置。比如在 __construct 里直接查,类可能尚未被扫描;在 onWorkerStart 或命令行 handle() 中调用才安全。
- 确保注解类已正确声明
@Annotation并继承AbstractAnnotation - 自定义注解类必须放在
app/Annotation(或配置中指定的扫描路径)下,且命名空间与目录结构一致 - 检查
config/autoload/annotations.php中的scan配置是否包含你的注解类所在目录 - 运行
php bin/hyperf.php di:scan后再启动服务(开发时建议开启scan.enable)
getClassesByAnnotation 第二个参数 $includeSubclasses 是干啥的?
这个布尔参数控制是否递归查找子类上标注了该注解的类。默认为 false,只返回直接标注了该注解的类;设为 true 后,若 A 类用了 @MyAnnotation,B 类继承 A 但没加注解,getClassesByAnnotation(MyAnnotation::class, true) 仍会返回 B —— 因为它“间接拥有”该注解语义。实际项目中极少需要开启,除非你在构建类似 Spring 的 AOP 继承链模型。
- 绝大多数场景保持默认
false即可 - 开启后性能无明显损耗,但语义容易混淆,调试时难定位真实标注位置
- 若依赖继承传播,建议改用
AnnotationCollector::getMethodsByAnnotation+ 手动向上遍历反射类
为什么 getClassesByAnnotation 找不到 Controller 方法上的注解?
getClassesByAnnotation 只查类级别注解(即写在 class 关键字上方的),方法、属性、参数上的注解得用对应方法:getMethodsByAnnotation、getPropertiesByAnnotation、getParametersByAnnotation。Controller 方法上常见的 @GetMapping、@Middleware 都是方法级注解,不会出现在 getClassesByAnnotation 结果里。
- 确认注解目标(
@Target)是否为Target::CLASS - 方法级注解请改用
AnnotationCollector::getMethodsByAnnotation(MyAnnotation::class) - 返回值是二维数组:
[类名 => [方法名 => 注解实例]],注意遍历方式
生产环境调用 AnnotationCollector 要注意什么?
扫描结果在容器启动时固化为静态数组,后续调用是纯内存读取,无 IO 开销。但要注意:热重载(如 Swoole reload)不会自动刷新注解缓存,修改注解后必须重启 Worker;另外,getClassesByAnnotation 不做运行时校验,若传入不存在的注解类名(如拼错类名),会静默返回空数组,不报错。
- 上线前用单元测试断言关键注解是否被正常收集,例如:
$this->assertNotEmpty(AnnotationCollector::getClassesByAnnotation(MyRoute::class)) - 避免在高频请求路径中反复调用(虽然快,但没必要),可考虑首次调用后缓存结果
- 注解类名必须带完整命名空间,
MyAnnotation::class比字符串'MyAnnotation'更安全











