Micronaut 3.9.1中带注解Bean用@Requires(missingBeans=)触发栈溢出错误
解决Micronaut中@Requires(missingBeans)配合注解处理器引发的StackOverflowError问题
问题背景
在Micronaut框架中,当Bean类被注解处理器(比如@Async、@NotNull这类会生成代理类的注解)处理时,给Bean实现类添加@Requires(missingBeans = {接口类.class})注解,会在Bean实例化阶段触发StackOverflowError。具体表现:
- 带有
@Async的ServiceOneImpl、带有@NotNull的ServiceTwoImpl注入时出现栈溢出 - 无额外注解的ServiceThreeImpl注入完全正常
- 移除
@Requires注解后,所有Service均可正常工作
解决方案
1. 调整@Requires的判断目标为实现类
注解处理器会为接口生成代理类,此时Micronaut容器中会存在接口类型的代理Bean,导致missingBeans=ServiceOne.class的判断陷入循环:容器检查是否存在ServiceOne类型Bean→发现代理类存在→代理类依赖ServiceOneImpl→ServiceOneImpl的@Requires又检查ServiceOne是否缺失,循环往复触发栈溢出。
修改实现类的@Requires注解,将missingBeans指向实现类本身:
// ServiceOneImpl修改后 @Singleton @Requires(missingBeans = ServiceOneImpl.class) public class ServiceOneImpl implements ServiceOne { @Async public void doSomething() { // 业务逻辑 } }
2. 用@Primary替代接口类型的missingBeans判断
如果需求是“当没有其他同接口Bean时,当前实现类生效”,可以改用@Primary标记默认实现,其他实现类通过优先级覆盖:
@Singleton @Primary public class ServiceOneImpl implements ServiceOne { @Async public void doSomething() { // 业务逻辑 } }
若需要替换默认实现,给新的实现类添加更高优先级即可:
@Singleton @Priority(1) public class AnotherServiceOneImpl implements ServiceOne { // 替代实现 }
3. 改用其他条件控制Bean加载
对于需要生成代理的Bean,避免用接口作为missingBeans的判断条件,改用实现类或属性配置来控制:
@Singleton @Requires(property = "service.one.enabled", defaultValue = "true") public class ServiceOneImpl implements ServiceOne { @Async public void doSomething() { // 业务逻辑 } }
临时规避方法
如果暂时无法修改注解逻辑,可以:
- 移除
@Async、@NotNull这类触发代理生成的注解,改用手动实现异步逻辑、手动参数校验 - 暂时注释掉
@Requires(missingBeans)注解,待后续版本修复或调整逻辑后再恢复
内容的提问来源于stack exchange,提问作者lorda
相关产品推荐
相关产品推荐

