Apache OpenWebBeans 4.1.1 配置参数详解
Apache OpenWebBeans 4.1.1 配置参数详解:配置文件位置(openwebbeans.properties)与系统属性/程序化覆盖优先级、SPI 服务替换、扫描与部署线程、代理映射、beans.xml 发现模式等参数总览与分类详解,含实测默认值(maxThreads=8、discovery=ALL)、生产配置模板与 FAQ。
Apache OpenWebBeans 4.1.1 配置参数详解
目标:系统讲解 Apache OpenWebBeans 4.1.1 作为 CDI 实现库时的配置项。OpenWebBeans 无服务端配置文件入口,其参数通过
openwebbeans.properties属性文件(classpath / 安装目录)、系统属性-D、SeContainerInitializer.addProperty()与beans.xml四类载体配置。本文对每个参数给出含义、实测默认值、设置方式与生产建议模板。所有默认值均在 Ubuntu 22.04.5 + JDK 21 + OpenWebBeans 4.1.1 环境实测读取。
一、环境信息
- 操作系统:Ubuntu 22.04.5 LTS
- Java:OpenJDK 21.0.12.1
- OpenWebBeans 版本:4.1.1(openwebbeans-se / openwebbeans-impl / openwebbeans-spi)
- CDI API:jakarta.enterprise.cdi-api 4.1.0
- 默认配置文件:
/opt/openwebbeans/config/openwebbeans.properties(二进制分发包自带,与 jar 内META-INF/openwebbeans/openwebbeans.properties同内容,17856 字节) - 示例工程:
/root/owb-demo/
二、前置条件
已安装 JDK 21 与 OpenWebBeans 4.1.1 依赖,并能正常编译运行示例工程:
export JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64
export PATH=$JAVA_HOME/bin:$PATH
cd /root/owb-demo
mvn -q compile
三、参数查看与修改方式
3.1 配置载体与覆盖优先级
| 载体 | 示例 | 优先级 |
|---|---|---|
| jar 内置默认值 | openwebbeans-impl.jar 内 META-INF/openwebbeans/openwebbeans.properties | 最低 |
| classpath 属性文件 | 应用 META-INF/openwebbeans/openwebbeans.properties | 中 |
| 系统属性 | java -Dorg.apache.webbeans.scanner.maxThreads=4 -jar app.jar | 高 |
| 程序化配置 | SeContainerInitializer.addProperty("key", "value") | 最高 |
💡 实测结论(读取
OpenWebBeansConfiguration验证):系统属性-D覆盖 classpath 文件值;未配置的键回落到文件/内置默认值;getProperty(key, default)在键不存在时返回传入的默认值。
3.2 运行期读取配置
程序内可通过 OpenWebBeans 配置 API 读取生效值(实测示例):
import org.apache.webbeans.config.OpenWebBeansConfiguration;
import org.apache.webbeans.config.WebBeansContext;
OpenWebBeansConfiguration cfg = WebBeansContext.getInstance().getOpenWebBeansConfiguration();
String v = cfg.getProperty("org.apache.webbeans.scanner.maxThreads"); // 实测默认 "8"
String d = cfg.getProperty("org.apache.webbeans.does.not.exist", "(fallback)"); // 键不存在返回 "(fallback)"
3.3 实测默认值(无任何覆盖时)
CONFIG scanner.maxThreads = 8
CONFIG deployer.maxThreads = 8
CONFIG defaultBeanDiscoveryMode = ALL
CONFIG ContainerLifecycle = org.apache.webbeans.lifecycle.StandaloneLifeCycle
四、参数总览
| 参数 | 实测默认值 | 作用 |
|---|---|---|
org.apache.webbeans.spi.ContainerLifecycle | StandaloneLifeCycle | 容器生命周期实现(SE 单机模式) |
org.apache.webbeans.spi.ScannerService | DefaultScannerService | 类路径扫描服务 |
org.apache.webbeans.scanner.maxThreads | 8 | 扫描器并行线程数 |
org.apache.webbeans.scanner.sliceSize | 1048576 | 扫描切片大小(字节) |
org.apache.webbeans.deployer.maxThreads | 8 | Bean 部署器并行线程数 |
org.apache.webbeans.defaultBeanDiscoveryMode | ALL | beans.xml 缺失时的默认发现模式 |
org.apache.webbeans.useBDABeansXMLScanner | false | 是否使用 BDA beans.xml 专用扫描器 |
org.apache.webbeans.spi.deployer.useEjbMetaDataDiscoveryService | false | 是否启用 EJB 元数据发现 |
org.apache.webbeans.spi.JNDIService | DefaultJndiService | JNDI 服务实现 |
org.apache.webbeans.spi.ContextsService | DefaultContextsService | 上下文(作用域)服务实现 |
org.apache.webbeans.spi.ConversationService | DefaultConversationService | 会话(Conversation)服务实现 |
org.apache.webbeans.spi.SecurityService | SimpleSecurityService | 安全服务实现 |
org.apache.webbeans.web.eagerSessionInitialisation | false | Web 部署时是否预初始化会话 |
org.apache.webbeans.scanExclusionPaths | 见 5.5 | 扫描排除路径列表 |
jakarta.enterprise.inject.allowProxying.classes | 空 | 允许代理的类名单(默认全部) |
beans.xml bean-discovery-mode | 由 beans.xml 指定 | 归档内 Bean 发现范围(all/annotated/none) |
五、核心参数分类详解
5.1 SPI 服务替换参数(容器架构层)
OpenWebBeans 通过 SPI 键把服务接口绑定到实现类,替换实现即可定制容器行为:
# 容器生命周期:SE 单机模式
org.apache.webbeans.spi.ContainerLifecycle=org.apache.webbeans.lifecycle.StandaloneLifeCycle
# 类路径扫描服务
org.apache.webbeans.spi.ScannerService=org.apache.webbeans.corespi.se.DefaultScannerService
# 上下文(作用域)服务
org.apache.webbeans.spi.ContextsService=org.apache.webbeans.corespi.se.DefaultContextsService
# JNDI 服务(SE 模式默认实现)
org.apache.webbeans.spi.JNDIService=org.apache.webbeans.corespi.se.DefaultJndiService
# 安全服务
org.apache.webbeans.spi.SecurityService=org.apache.webbeans.corespi.security.SimpleSecurityService
⚠️ 注意:这些键在容器启动期被读取并实例化。实测把
org.apache.webbeans.spi.ScannerService指向不存在的类后启动,容器立即报WebBeansException: Class not found exception in creating instance with class : demo.bogus.NonexistentScannerService——可用于校验自定义 SPI 实现是否正确。
5.2 扫描与部署并行度参数
批量扫描/部署 Bean 时使用的并行线程数,影响大归档启动速度:
# 扫描器并行线程数,实测默认 8
org.apache.webbeans.scanner.maxThreads = 8
# 扫描切片大小(字节),实测默认 1048576(1MB)
org.apache.webbeans.scanner.sliceSize = 1048576
# Bean 部署器并行线程数,实测默认 8
org.apache.webbeans.deployer.maxThreads = 8
💡 说明:小内存机器(如 512MB 堆)可调低到 2–4 减少并发线程开销;大归档(数千 Bean)可适度调高。
5.3 代理映射参数(作用域代理)
为各内置作用域指定拦截处理器(客户端代理内部委托链):
org.apache.webbeans.proxy.mapping.jakarta.enterprise.context.ApplicationScoped=org.apache.webbeans.intercept.ApplicationScopedBeanInterceptorHandler
org.apache.webbeans.proxy.mapping.jakarta.enterprise.context.RequestScoped=org.apache.webbeans.intercept.RequestScopedBeanInterceptorHandler
org.apache.webbeans.proxy.mapping.jakarta.enterprise.context.SessionScoped=org.apache.webbeans.intercept.SessionScopedBeanInterceptorHandler
💡 说明:运行时通过
容器.select(X.class).get().getClass().getName()可观察到demo.GreetingService$$OwbNormalScopeProxy0这样的代理类名(实测回显),即本组映射的产物。
5.4 Bean 发现模式参数
org.apache.webbeans.defaultBeanDiscoveryMode:beans.xml 缺失时的归档默认发现模式,实测默认ALL。beans.xml中bean-discovery-mode三档:
| 取值 | 扫描范围 |
|---|---|
| all | 扫描归档内全部类(含无注解类,均作为候选) |
| annotated | 仅扫描带 Bean 定义注解的类 |
| none | 归档内不扫描(仅显式声明的 Bean/扩展生效) |
<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" bean-discovery-mode="all">
</beans>
5.5 扫描排除路径参数
org.apache.webbeans.scanExclusionPaths:路径片段命中即跳过(逗号/反斜杠续行分隔),用于加速启动、避免扫描无关 jar。实测默认值包含:
/jre/lib, /Contents/Home/, /dt.jar, /tools.jar, /bootstrap.jar, /asm, /javassist,
/xbean-, /jconsole.jar, /geronimo-connector, /geronimo-j2ee-, /geronimo-jpa_,
/geronimo-javamail, /geronimo-transaction, /commons-, /arquillian-, /bsh-,
/shrinkwrap-, /junit-, /testng-, /openjpa-, /bcel, /hamcrest, /mysql-connector,
/idea_rt, /eclipse, /jcommander, /tomcat, /catalina, /jasper, /jsp-api,
/myfaces-api, /myfaces-impl, /jakarta.faces, /servlet-api, /javax,
/annotation-api, /el-api, /mojarra, /sisu-guice-, /sisu-inject-, /aether-,
/plexus-, /maven-, /guava-(完整默认清单以 /opt/openwebbeans/config/openwebbeans.properties 为准)
5.6 其他常用参数
# 是否启用 EJB 元数据发现(EJB 插件场景)
org.apache.webbeans.spi.deployer.useEjbMetaDataDiscoveryService=false
# 是否使用 BDA beans.xml 专用扫描器
org.apache.webbeans.useBDABeansXMLScanner=false
# Web 部署时是否预初始化 HttpSession(Web 插件场景)
org.apache.webbeans.web.eagerSessionInitialisation=false
# 允许代理的类名单(默认全部可代理)
jakarta.enterprise.inject.allowProxying.classes=
5.7 JVM 参数(Java 进程内存)
SE 容器 Bean、代理类与内部结构驻留 JVM 堆,按规范限制在 256–512MB:
export MAVEN_OPTS="-Xms256m -Xmx512m" # mvn exec:java 运行主类时
java -Xms256m -Xmx512m -jar app.jar # 独立运行 jar 时
生效验证(运行期间):
ps -ef | grep [j]ava | grep -oE "\-Xm[sx][0-9]+m" | sort -u
实测回显:
-Xms256m
-Xmx512m
六、生产配置模板
💡 适用场景:
16GB 内存、NVMe SSD、数千 Bean 的 CDI 服务(SE 或 Web 部署)。
将以下内容写入应用 classpath 下的 META-INF/openwebbeans/openwebbeans.properties(文件名与路径必须精确,否则不生效):
# 容器生命周期:SE 单机模式
org.apache.webbeans.spi.ContainerLifecycle=org.apache.webbeans.lifecycle.StandaloneLifeCycle
# 扫描与部署并行度:16GB 内存机器适度并行
org.apache.webbeans.scanner.maxThreads = 8
org.apache.webbeans.deployer.maxThreads = 8
# 默认 Bean 发现模式
org.apache.webbeans.defaultBeanDiscoveryMode=ALL
# 跳过无关框架 jar,加速启动
org.apache.webbeans.scanExclusionPaths=/jre/lib, /dt.jar, /tools.jar, /maven-, /junit-, /testng-
# 保持默认 SPI(如需自定义请替换为实现类全限定名)
org.apache.webbeans.spi.JNDIService=org.apache.webbeans.corespi.se.DefaultJndiService
同时用 beans.xml 声明归档发现模式,并限制 JVM 堆:
| 场景 | 推荐配置 |
|---|---|
| 演示/测试(小内存) | bean-discovery-mode="annotated" + -Xms256m -Xmx512m + 默认线程数 |
| 生产/中小服务(8GB RAM) | bean-discovery-mode="all" + -Xms256m -Xmx512m + maxThreads=8 |
| 生产/大规模(16GB RAM) | bean-discovery-mode="all" + -Xms512m 上限内调优 + maxThreads=8~16 |
| 最小化启动耗时 | 补充 scanExclusionPaths 排除无关 jar + 调低线程数 |
⚠️ 注意:
scanExclusionPaths用/开头且以逗号+反斜杠续行的写法;每条为路径片段(子串匹配),命中即跳过扫描。
七、常见问题
Q1:怎么确认配置确实生效?
程序内用 WebBeansContext.getInstance().getOpenWebBeansConfiguration().getProperty(key) 读取并打印(实测回显见 3.3);或故意把 SPI 指向不存在的类,观察启动报错是否包含该类名(5.1)。
Q2:classpath 属性文件为什么不生效?
文件名与路径必须为 META-INF/openwebbeans/openwebbeans.properties(注意两层目录)。放错位置(如 openwebbeans.properties、META-INF/openwebbeans.properties)实测均不生效。
Q3:系统属性和属性文件谁优先?
系统属性优先(实测 -Dorg.apache.webbeans.scanner.maxThreads=6 覆盖文件中的 2);SeContainerInitializer.addProperty() 优先级最高。
Q4:bean-discovery-mode 三档怎么选?
all 最省心但扫描量大;annotated 只扫描带 Bean 定义注解的类,启动更快;none 用于只靠扩展/显式注册的归档。生产推荐 annotated 或 all。
Q5:org.apache.webbeans.spi.ScannerService 改了但没生效?
该键在容器启动期读取,修改后必须重启 JVM;且实现类必须在 classpath 中、有无参构造器,否则报 WebBeansException: Unable to instantiate class(实测现象)。
Q6:SE 容器堆内存多大合适?
按规范 256–512MB 起步;Bean 数量大、事件频繁时取上限 512MB。用 ps -ef | grep [j]ava 核对 -Xms/-Xmx 生效(实测回显见 5.7)。
八、参考链接
- OpenWebBeans 官网:
https://openwebbeans.apache.org/ - 默认配置参考文件:
/opt/openwebbeans/config/openwebbeans.properties - CDI 4.0 规范:
https://jakarta.ee/specifications/cdi/4.0/ - OpenWebBeans 文档:
https://openwebbeans.apache.org/documentation.html