使用CDI的@Named和@Inject时出现NoSuchBeanDefinitionException异常
问题描述
- 使用Spring原生的
@Component和@Autowired注解时,可正常访问Spring容器中的Bean - 替换为CDI规范的
@Named(javax.inject包下)和@Inject注解后,无法通过applicationContext.getBean(CdiBiz.class)获取Bean,报错触发于该行代码 - 已在
pom.xml中引入javax.inject依赖,Maven依赖列表中存在包含@Named、@Inject等6个注解的javax.inject-1.jar - 补充:将
javax.inject替换为jakarta.inject可解决该问题
应用代码
package tempTestCdiError; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; @SpringBootApplication public class CdiTestApp { static Logger LOGGER = LoggerFactory.getLogger(CdiTestApp.class); public static void main(String[] args) { ConfigurableApplicationContext applicationContext = SpringApplication.run(CdiTestApp.class, args); CdiBiz business = applicationContext.getBean(CdiBiz.class); LOGGER.info("{}, dao-{}", business, business.getCdiDao()); } }
原因分析与解决方案
核心原因
Spring Boot 3.0及以上版本已全面迁移到Jakarta EE规范,不再兼容旧的Java EE(javax.*包)相关API。javax.inject属于Java EE规范范畴,Spring Boot 3.x默认不会识别javax.inject.Named和javax.inject.Inject注解来创建、管理Bean,因此无法从容器中获取对应实例。
解决方案
方案1:切换为Jakarta EE规范依赖(推荐)
将pom.xml中的javax.inject依赖替换为jakarta.inject:
<!-- 移除旧的javax.inject依赖 --> <!-- <dependency> <groupId>javax.inject</groupId> <artifactId>javax.inject</artifactId> <version>1</version> </dependency> --> <!-- 添加Jakarta版本的依赖 --> <dependency> <groupId>jakarta.inject</groupId> <artifactId>jakarta.inject-api</artifactId> <version>2.0.1</version> </dependency>
同时将代码中的导入语句从import javax.inject.Named;、import javax.inject.Inject;改为import jakarta.inject.Named;、import jakarta.inject.Inject;,Spring容器即可正常识别并管理这些Bean。
方案2:降级Spring Boot版本(不推荐)
若必须使用javax.inject,可将Spring Boot版本降级到2.x系列,该版本仍兼容Java EE(javax.*)规范,能正常识别javax.inject下的注解。但此方案会错过Spring Boot 3.x的新特性、性能优化与安全更新,不建议长期使用。
内容的提问来源于stack exchange,提问作者Crystal DarkStar
相关产品推荐
相关产品推荐

