beans.xml 是 jakarta ee 中 cdi 的启用标记,非 spring 配置文件;需置于 meta-inf/ 或 web-inf/ 下,文件名严格小写,内容可为空或含最小命名空间声明,版本影响扫描模式,与 spring 混用易引发注入冲突。

beans.xml 是 CDI 的开关,不是 Spring 的配置文件
很多人在项目里放一个 beans.xml,以为它是 Spring 的替代品或同类配置——其实它和 Spring 完全无关。Spring 用的是 applicationContext.xml 或注解驱动,而 beans.xml 是 Java EE / Jakarta EE 中 CDI(Contexts and Dependency Injection)规范的启用标记。
它的作用非常窄:只要存在(且路径正确),容器就开启 CDI 扫描和注入能力;内容为空也完全合法。
- 必须放在
META-INF/(Java SE)或WEB-INF/(Web 应用)目录下 - 文件名必须是
beans.xml,大小写敏感 - Spring Boot 项目默认不加载它,除非你显式引入了
jakarta.enterprise.cdi-api并启用 CDI 兼容层 - 如果项目没用到
@Inject、@Named、@Dependent这类 CDI 注解,这个文件可以删掉
beans.xml 里写什么?几乎什么都不用写
CDI 规范允许 beans.xml 为空,或者只含最简声明。它不像 Spring XML 那样定义 bean、aop、事务等逻辑。
常见错误是往里面抄 Spring 的 <bean></bean> 标签,或试图用它注册组件——这不会生效,CDI 不解析那些元素。
- 最小合法内容(Jakarta EE 9+):
<?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"> </beans> -
version属性影响扫描行为:设为"4.0"表示启用 bean 发现模式(默认annotated),设为"3.0"或更低可能触发全类扫描(性能差) - 想禁用某个模块的 CDI 扫描?加
<scan><exclude name="com.example.unwanted.*"></exclude></scan>,但注意不是所有容器都支持
和 Spring @Autowired 混用会出什么问题
在同一个项目里同时启用 Spring 和 CDI(比如用了 spring-context 又加了 cdi-api),@Autowired 和 @Inject 可能指向不同实例,甚至引发循环依赖失败。
典型现象是:一个类用 @Inject 注入成功,换成 @Autowired 就报 NoUniqueBeanDefinitionException;或者 @PostConstruct 方法没被调用——说明生命周期管理权被两个容器抢夺了。
- Spring 默认忽略
beans.xml,除非你手动配置CdiBeanFactoryPostProcessor - WildFly、Payara 等应用服务器自带 CDI,Spring Boot 嵌入式容器默认不带,混用前先确认运行环境
- 优先选一种注入风格:Spring 项目坚持用
@Autowired+@Component,Jakarta EE 项目用@Inject+@ApplicationScoped
为什么我的 beans.xml 没生效?检查这三点
最常见的“没生效”不是配置错,而是路径、命名、版本三者中至少一个没对上。
- 路径是否正确:
META-INF/beans.xml(jar 包)或WEB-INF/beans.xml(war 包),不能放在src/main/resources下直接编译过去(Maven 默认不会把它放进META-INF) - 文件名是否拼错:比如写成
Beans.xml、beans.xml.bak或beans.xml~,CDI 容器只认严格的小写beans.xml - 依赖是否到位:JDK 17+ 的 Jakarta EE 9+ 项目需引用
jakarta.enterprise:jakarta.enterprise.cdi-api,旧项目用javax.enterprise:cdi-api,两者不可混用
CDI 的启用是静默的,没有日志提示“已加载 beans.xml”。最简单的验证方式:写一个空类加 @ApplicationScoped,再用 @Inject 尝试注入,失败就回头查这三项。










