Micronaut 2.2.0迁移至3.5.0遇NoSuchBeanException及注解问题
Micronaut 2.2.0 迁移至3.5.0 注入问题排查
问题背景
按官方文档将应用从Micronaut 2.2.0迁移到3.5.0,核心变更涉及注入注解:
- javax.inject不再是传递依赖,Micronaut自带Jakarta inject注解
- 可选方案:全量替换
javax.inject导入为jakarta.inject,或添加javax-inject依赖继续使用旧注解
遇到的具体问题:
- 移除javax inject依赖并替换所有导入后,编译报错
javax.inject.Singleton未找到,已确认无外部依赖引入javax包 - 添加javax.inject依赖后编译通过,但集成测试抛出
NoSuchBeanException,Controller中@Inject注入的clock对象无法找到 - 启用
io.micronaut.context.condition调试日志后,发现多个测试相关Bean因TestActiveCondition条件不满足未加载,同时出现Failed to inject value for parameter [responseMapper] of class: com.csg.pb.scot.calculation.engine.InceptionCalculationService错误
原因分析
1. 编译时javax.inject.Singleton未找到
- 存在未替换的隐式引用:比如第三方依赖残留、Micronaut自动生成的代理类、或IDE/构建缓存中的旧代码
- 迁移初期注解处理器可能仍生成引用javax.inject的代码,若项目混合新旧注解会触发该问题
2. 添加javax依赖后测试注入失败
- 注解冲突:同时存在javax.inject和jakarta.inject时,Micronaut容器无法正确识别和注册Bean,导致依赖链断裂
- 测试Bean未加载:
TestActiveCondition失败说明测试Mock Bean(如MockInceptionCalculationService)未被加载,进而引发responseMapper、clock的注入异常 - 扫描范围配置错误:迁移后Bean扫描范围调整不当,导致Clock等核心Bean未被容器扫描到
解决步骤
彻底替换javax.inject注解
- 全局替换所有
import javax.inject.*为import jakarta.inject.*,覆盖业务代码、测试代码中的@Inject、@Singleton、@Named等注解 - 清理构建和IDE缓存:
- Gradle:执行
./gradlew clean build --no-build-cache - Maven:执行
mvn clean install -Dmaven.clean.failOnError=false
- Gradle:执行
- 检查第三方依赖:若依赖仍使用javax.inject,升级到支持Jakarta的版本,或添加
jakarta.inject:jakarta.inject-api依赖并确保其优先级高于javax依赖
修复测试Bean加载问题
- 检查测试类注解:确保测试类添加
@MicronautTest,并配置正确测试环境(如@MicronautTest(environments = "test")) - 验证Mock Bean定义:确保Mock类添加
@Singleton或@Replaces注解,且所在包被纳入扫描范围 - 调整扫描配置:在
application-test.yml中配置micronaut.application.packages,明确指定需要扫描的测试相关包
验证Clock Bean注册
- 检查Clock实现类是否添加
jakarta.inject.Singleton注解 - 确保配置文件中启用Micronaut自带Clock:
micronaut.time.enabled=true - 测试中可显式注册Clock Bean:
@MicronautTest public class YourTestClass { @Bean Clock clock() { return Clock.systemUTC(); } }
内容的提问来源于stack exchange,提问作者Nitin Bisht
相关产品推荐
相关产品推荐

