Quarkus 2.9.2下CDI @Decorator装饰器递归调用问题
Quarkus CDI装饰器调用无限递归问题修复方案
问题根因
- 核心触发点是装饰器的
@Delegate注入点额外添加了@Any注解:CDI容器对@Delegate注入点有特殊匹配逻辑,会自动排除装饰器本身的代理实例,只匹配真实业务实现Bean;添加@Any后会绕过这套特殊规则,将所有实现SomeRepository接口的Bean都纳入候选,包括装饰器自身生成的CDI代理,最终注入的delegate对象就是装饰器自己,调用方法时会反复进入装饰器逻辑形成无限递归。 - 多模块场景下如果未配置Jandex索引,Quarkus无法正确扫描到非当前模块的Bean实现,会进一步加剧委托对象匹配错误的问题。
- 此前尝试的调整装饰器/拦截器优先级、移除拦截器、将装饰器改为抽象类的方案,均未触及委托注入点匹配规则错误的核心问题,因此无法解决递归故障。
修复步骤
- 移除
@Delegate注入点上的@Any注解,恢复CDI容器对装饰器委托的默认匹配逻辑,修改后的装饰器代码如下:
@Decorator public class MyDecorator implements SomeRepository { @Inject @Delegate SomeRepository delegate; // 移除原有的@Any注解 private boolean canAccess() { // 原有业务权限校验逻辑 return true; } @Override public Entity get(Long id) { if (!canAccess()) { throw new RuntimeException("Access not allowed"); } return delegate.get(id); } // 其余接口方法保持原有逻辑不变 }
- 给仓储层真实实现类显式指定优先级,避免多模块下Bean排序异常导致匹配错误:
@ApplicationScoped @Priority(100) // 普通业务Bean优先级设为100,低于装饰器默认优先级,确保被委托正确选中 public class DefaultSomeRepositoryRepository implements SomeRepository { // 原有依赖注入保持不变 @Override public Entity get(Long id) { // 原有数据库查询逻辑不变 return new Entity(); } // 其余接口方法保持原有逻辑不变 }
- 给所有非启动模块(usecase、repository模块)添加Jandex插件配置,确保Quarkus能正确扫描到跨模块的CDI Bean,在对应模块的pom.xml中添加如下插件配置:
<build> <plugins> <plugin> <groupId>io.quarkus</groupId> <artifactId>quarkus-jandex-maven-plugin</artifactId> <version>2.9.2.Final</version> <executions> <execution> <id>build-jandex-index</id> <goals> <goal>jandex</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
配置完成后执行mvn clean install重新构建项目,重启应用即可解决递归问题,装饰器会正常将请求委托给真实的仓储实现Bean,绑定的日志拦截器逻辑也可正常执行。
内容的提问来源于stack exchange,提问作者Michael Burgstaller
相关产品推荐
相关产品推荐

