Apache DeltaSpike 配置参数详解
详解 Apache DeltaSpike 配置体系:配置文件位置与加载验证、四类配置源与取值优先级、@ConfigProperty 与 ConfigResolver 用法,以及 Data 模块 JPA 事务配置。
Apache DeltaSpike 配置参数详解
DeltaSpike 的配置能力由 deltaspike-core 提供:把属性文件、系统属性、环境变量、JNDI 统一抽象为配置源(ConfigSource),按优先级解析,并支持 @ConfigProperty 声明式注入与 ConfigResolver 编程式取值。本文中的优先级与覆盖结论均经真实运行验证。
一、配置文件与加载位置
1.1 默认配置文件
DeltaSpike 默认读取类路径下的 META-INF/apache-deltaspike.properties。文件内容即普通 key=value:
app.greeting=Hello DeltaSpike
app.name=Apache DeltaSpike
app.version=1.9.6
1.2 文件位置与生效验证
在 DeltaSpike 1.9.6 上分别验证了多个候选位置,实测结论如下:
| 文件位置 | 是否生效 |
|---|---|
META-INF/apache-deltaspike.properties | 生效(默认) |
deltaspike.properties(类路径根) | 不生效 |
apache-deltaspike.properties(类路径根) | 不生效 |
仅 META-INF/apache-deltaspike.properties 会被加载。启动时日志会打印命中信息:
INFO: Custom config found by DeltaSpike. Name: 'META-INF/apache-deltaspike.properties', URL: 'file:/root/deltaspike-demo/target/classes/META-INF/apache-deltaspike.properties'
二、配置源与取值优先级
2.1 内置配置源与 ordinal
调用 ConfigResolver.getConfigSources() 打印各源,真实回显:
[DeltaSpike] #1 ordinal=400 source=org.apache.deltaspike.core.impl.config.SystemPropertyConfigSource
[DeltaSpike] #2 ordinal=300 source=org.apache.deltaspike.core.impl.config.EnvironmentPropertyConfigSource
[DeltaSpike] #3 ordinal=200 source=org.apache.deltaspike.core.impl.config.LocalJndiConfigSource
[DeltaSpike] #4 ordinal=100 source=org.apache.deltaspike.core.impl.config.PropertyFileConfigSource
ordinal 越大优先级越高,即:
- 系统属性(system-properties,400)
- 环境变量(environment-properties,300)
- JNDI(200)
- 属性文件(property-file,100)
2.2 覆盖实验
以 app.greeting 为例,分别在真实环境执行:
| 实验 | 命令片段 | 取值结果 |
|---|---|---|
| 属性文件默认 | 无额外参数 | Hello DeltaSpike |
| 系统属性覆盖 | -Dapp.greeting=SYS_PLAIN | SYS_PLAIN |
| 环境变量覆盖 | 环境变量 app_greeting=ENV_VAL | ENV_VAL |
结论:系统属性与环境变量都能覆盖属性文件;环境变量名由属性键把 . 替换为 _ 得到(app.greeting → app_greeting)。
三、@ConfigProperty 使用详解
3.1 基本注入
在 bean 中对字段使用 @ConfigProperty 声明键名:
import javax.inject.Inject;
import org.apache.deltaspike.core.api.config.ConfigProperty;
@Inject
@ConfigProperty(name = "app.name")
private String name;
键不存在且未提供默认值时,注入结果为 null。
3.2 提供默认值
@Inject
@ConfigProperty(name = "app.greeting", defaultValue = "Hi")
private String greeting;
当 app.greeting 在所有配置源中都不存在时,使用 Hi。实测在缺失该键时输出 app.greeting = Hi。
3.3 与 ConfigResolver 编程式配合
不适合注入的场景可编程取值:
import org.apache.deltaspike.core.api.config.ConfigResolver;
String v = ConfigResolver.getPropertyValue("app.version", "unknown");
getPropertyValue(key) 与 getPropertyValue(key, defaultValue) 两个重载分别返回键值或默认值。实测输出 app.version = 1.9.6。
四、deltaspike 保留命名空间与系统属性前缀
4.1 deltaspike. 前缀
DeltaSpike 自身配置项统一使用 deltaspike. 前缀命名空间,例如 deltaspike.application.name、deltaspike.config.log、deltaspike.bean.isolation.level。这些键可像普通键一样通过系统属性传入,并被 ConfigResolver 读取。实测:
mvn -B -Ddeltaspike.bean.isolation.level=LENIENT exec:java \
-Dexec.mainClass=com.example.ConfigSourcesApp
回显:
[DeltaSpike] deltaspike.bean.isolation.level = LENIENT
4.2 环境变量前缀形态
由于环境变量名不允许出现 .,环境源在按原名查不到时会把 . 替换为 _ 再查一次。因此 deltaspike. 命名空间下的键,其环境变量形态为 deltaspike_...,例如 deltaspike.application.name 对应环境变量 deltaspike_application_name。
4.3 常见内置配置键
从 deltaspike-core 制品中可提取到的内置键(节选):
| 配置键 | 说明 |
|---|---|
| deltaspike.application.name | 应用名 |
| deltaspike.config.log | 置为 true 时在启动阶段打印全部配置源与已解析值 |
| deltaspike.bean.isolation.level | Bean 隔离级别 |
| deltaspike.scope.window.max | Window 作用域窗口数量上限 |
| deltaspike.mbean.auto / deltaspike.mbean.category | MBean 自动注册与分类 |
| deltaspike.interdyn.enabled / deltaspike.interdyn.rule | 动态拦截开关与规则 |
| deltaspike.interceptor.priority | 拦截器优先级 |
| deltaspike.futureable.termination | 异步结果终止行为 |
| deltaspike.validation.violation | 校验违规处理策略 |
开启配置日志实测:
mvn -B -Ddeltaspike.config.log=true exec:java
回显中会看到 ConfigSources: 与 Configured Values: 明细,便于排查键名与优先级问题。
五、i18n 与 messageResolver
5.1 MessageContext 注入与插值
MessageContext 由 DeltaSpike 生产,可直接注入 bean:
import javax.inject.Inject;
import org.apache.deltaspike.core.api.message.MessageContext;
@Inject
private MessageContext messageContext;
public void run() {
String msg = messageContext.message()
.template("Welcome %s, running DeltaSpike %s")
.argument("Apache DeltaSpike").argument("1.9.6")
.toString();
System.out.println(msg);
}
实测输出:Welcome Apache DeltaSpike, running DeltaSpike 1.9.6。默认插值器按 String.format(%s)风格解析,占位符应使用 %s。
5.2 替换消息解析器 messageResolver
MessageContext 支持替换消息解析器与消息源,以对接自定义国际化资源:
MessageContext ctx = messageContext.clone()
.messageResolver(myMessageResolver) // 自定义 MessageResolver
.messageSource("com.example.messages") // 资源基名
.localeResolver(myLocaleResolver);
messageResolver(MessageResolver):替换默认解析器,用于从自定义载体(数据库、远端配置中心等)取消息模板。messageSource(String...):指定消息资源基名,配合@MessageBundle使用。localeResolver(LocaleResolver):指定语言环境解析策略。
六、Data 模块的 JPA 事务与数据源配置
本节为 Data 模块的集成用法参考(基于 DeltaSpike 公开 API),未在本次实验中逐项运行。
6.1 依赖与 @Repository
引入 Data 模块:
<dependency>
<groupId>org.apache.deltaspike.modules</groupId>
<artifactId>deltaspike-data-module-api</artifactId>
<version>1.9.6</version>
</dependency>
<dependency>
<groupId>org.apache.deltaspike.modules</groupId>
<artifactId>deltaspike-data-module-impl</artifactId>
<version>1.9.6</version>
<scope>runtime</scope>
</dependency>
声明仓储接口,DeltaSpike 会生成实现:
@Repository
public interface UserRepository extends EntityRepository<User, Long> {
List<User> findByNameLike(String name);
}
6.2 数据源与持久化单元
数据源与持久化单元仍由标准 JPA 机制配置,放在 META-INF/persistence.xml:
<persistence-unit name="demoPU" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:h2:mem:demo;DB_CLOSE_DELAY=-1"/>
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
</properties>
</persistence-unit>
6.3 事务
- 受管事务:在 EJB/JTA 环境下由应用服务器事务管理,仓储方法参与 JTA 事务。
- 非受管(RESOURCE_LOCAL):使用
@Transactional显式划分事务边界:
import org.apache.deltaspike.jpa.api.transaction.Transactional;
@Transactional
public void createUser(User user) {
userRepository.save(user);
}
@Transactional 也可通过 deltaspike.jpa.api.transaction.Transactional 的 qualifier 属性指定事务管理器。
七、配置排错
Q1:@ConfigProperty 注入值为 null?
依次检查:配置文件是否位于 META-INF/apache-deltaspike.properties;键名拼写是否一致;是否被更高优先级源覆盖。必要时用 -Ddeltaspike.config.log=true 打印全部配置源。
Q2:系统属性为什么不生效?
exec:java 与直接 java -Dkey=value 场景下,系统属性都属最高优先级源;若使用 -Dfoo 却读取 bar,则是键名不匹配,而非优先级问题。
Q3:环境变量配置不生效?
确认变量名由键名的 . 替换为 _ 得到,且未被同名系统属性或属性文件以外的更高优先级源覆盖。
Q4:如何限制 JVM 堆以节省资源?
构建或运行示例时可设置 MAVEN_OPTS="-Xms256m -Xmx512m"。