升级技术栈后CDI注入返回NULL问题求助
Tomcat 10.1 + Jakarta EE 升级后CDI注入NULL问题解决指南
核心问题定位
从Java EE 8/Tomcat9/Java8升级到Jakarta EE/Tomcat10.1/Java21后,CDI注入失效的核心原因通常是新旧API包名混用、CDI容器未正确初始化,或是JAX-RS与CDI集成配置缺失。以下是针对性的解决方案:
第一步:统一CDI实现(二选一,不要混用)
Tomcat本身不自带CDI容器,必须手动引入实现,Weld和OpenWebBeans都可兼容Jakarta EE 10,选其一即可。
方案一:使用Weld Servlet(生态更成熟)
- Maven依赖配置(确保是Jakarta版本)
<dependency> <groupId>org.jboss.weld.servlet</groupId> <artifactId>weld-servlet-shaded</artifactId> <version>5.1.2.Final</version> <!-- 匹配Jakarta EE 10与Tomcat10.1 --> <scope>runtime</scope> </dependency>
- 初始化CDI容器
- 方式1:修改
web.xml添加监听器
<listener> <listener-class>org.jboss.weld.environment.servlet.Listener</listener-class> </listener> <resource-env-ref> <description>CDI Bean Manager工厂</description> <resource-env-ref-name>BeanManager</resource-env-ref-name> <resource-env-ref-type>jakarta.enterprise.inject.spi.BeanManager</resource-env-ref-type> </resource-env-ref>- 方式2:代码注解式初始化(无需修改web.xml)
@WebListener public class WeldInitListener extends org.jboss.weld.environment.servlet.Listener {} - 方式1:修改
- beans.xml配置(放在
src/main/resources/META-INF/下,必须用Jakarta命名空间)
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="https://jakarta.ee/xml/ns/jakartaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/beans_4_0.xsd" version="4.0" discovery-mode="all"> </beans>
方案二:使用OpenWebBeans
- Maven依赖配置
<dependency> <groupId>org.apache.openwebbeans</groupId> <artifactId>openwebbeans-servlet</artifactId> <version>4.0.2</version> <!-- 兼容Jakarta EE 10 --> <scope>runtime</scope> </dependency> <!-- 若需JAX-RS集成,额外添加 --> <dependency> <groupId>org.apache.openwebbeans</groupId> <artifactId>openwebbeans-jaxrs</artifactId> <version>4.0.2</version> <scope>runtime</scope> </dependency>
- web.xml配置
<listener> <listener-class>org.apache.webbeans.servlet.WebBeansConfigurationListener</listener-class> </listener> <listener> <listener-class>org.apache.webbeans.servlet.WebBeansServletContextListener</listener-class> </listener> <resource-env-ref> <resource-env-ref-name>BeanManager</resource-env-ref-name> <resource-env-ref-type>jakarta.enterprise.inject.spi.BeanManager</resource-env-ref-type> </resource-env-ref>
- beans.xml配置与Weld方案一致,必须使用Jakarta命名空间。
第二步:关键检查点(必做)
彻底替换javax为jakarta注解
所有CDI、JAX-RS相关注解必须是Jakarta包下的:@ApplicationScoped→jakarta.enterprise.context.ApplicationScoped@Inject→jakarta.inject.Inject@Path/@GET→jakarta.ws.rs.Path/jakarta.ws.rs.GET
混用javax和jakarta注解会直接导致CDI容器无法识别Bean。
清理残留的javax依赖
检查Maven依赖树,确保所有旧Java EE依赖(如javax.servlet-api、javax.ws.rs-api)已替换为Jakarta版本(jakarta.servlet-api、jakarta.ws.rs-api)。JAX-RS与CDI集成配置
若使用Jersey作为JAX-RS实现,需添加CDI集成依赖:
<dependency> <groupId>org.glassfish.jersey.ext.cdi</groupId> <artifactId>jersey-cdi1x</artifactId> <version>3.1.5</version> <!-- 匹配Jakarta EE 10 --> </dependency>
确保JAX-RS资源类被CDI容器管理,否则@Inject不会生效。
- 验证CDI容器初始化
启动Tomcat后查看日志:- Weld会输出
WELD-000900: 5.1.2.Final (Final) - OpenWebBeans会输出
OpenWebBeans Container is starting...
无相关日志则说明容器未正确初始化,需检查依赖或监听器配置。
- Weld会输出
验证方法
在MyService中添加@PostConstruct方法,启动后查看控制台输出:
@PostConstruct public void init() { System.out.println("MyService已被CDI容器初始化"); }
若未输出该日志,说明Bean未被CDI识别,需回头检查注解包名和beans.xml配置。
内容的提问来源于stack exchange,提问作者Samanite
相关产品推荐
相关产品推荐

