在程序中读取配置信息
Java Chassis支持使用一致的API获取配置,开发者不需要关注从哪里读取配置项的 值,Java Chassis会自动从各处读取配置,并按照优先级进行合并以保证用户取到的是优先级最高的配置值。读取配置信息支持下面几种不同的方式。
使用 archaius API
DynamicDoubleProperty myprop = DynamicPropertyFactory.getInstance()
.getDoubleProperty("trace.handler.sampler.percent", 0.1);
以上例子表示声明了一个key为trace.handler.sampler.percent
的动态配置对象,默认值为0.1
。
关于配置项API的具体方法可参考archaius API。
archaius API 支持callback处理配置变更:
myprop.addCallback(new Runnable() {
public void run() {
// 当配置项的值变化时,该回调方法会被调用
System.out.println("trace.handler.sampler.percent is changed!");
}
});
使用Java Chassis配置注入机制
配置注入提供了一种简单的管理大量复杂配置的机制,开发者不需要使用 DynamicPropertyFactory 逐个读取配置项,增加配置监听, 而是定义一个简单的 JAVA Bean, 定义这个 Bean 的属性对应的配置项, 当配置信息变化的时候, Bean 的属性会自动刷新,极大 的简化了用户管理大量复杂配置的复杂度。
Bean 属性对应的配置项名称支持通配符, 一个属性可以关联若干配置项,可以声明这些配置项的优先级。 Java对象可以是一个 Java Bean,或是一个拥有public字段的类。
- 配置注入对象
我们首先设计两个Java类用于注入配置属性,分别用来演示不使用注解和使用注解的场景。使用注解:
```Java
@InjectProperties(prefix = "jaxrstest.jaxrsclient")
public class Configuration {
/*
* 方法的 prefix 属性值 "override" 会覆盖标注在类定义的 @InjectProperties
* 注解的 prefix 属性值。
*
* keys属性可以为一个字符串数组,下标越小优先级越高。
*
* 这里会按照如下顺序的属性名称查找配置属性,直到找到已被配置的配置属性,则停止查找:
* 1) jaxrstest.jaxrsclient.override.high
* 2) jaxrstest.jaxrsclient.override.low
*
* 测试用例:
* jaxrstest.jaxrsclient.override.high: hello high
* jaxrstest.jaxrsclient.override.low: hello low
* 预期:
* hello high
*/
@InjectProperty(prefix = "jaxrstest.jaxrsclient.override", keys = {"high", "low"})
public String strValue;
/**
* keys支持通配符,并在可以在将配置属性注入的时候指定通配符的代入对象。
*
* 测试用例:
* jaxrstest.jaxrsclient.k.value: 3
* 预期:
* 3
*/
@InjectProperty(keys = "${key}.value")
public int intValue;
/**
* 通配符的代入对象可以是一个字符串List,优先级遵循数组元素下标越小优先级越高策略。
*
* 测试用例:
* jaxrstest.jaxrsclient.l1-1: 3.0
* jaxrstest.jaxrsclient.l1-2: 2.0
*
* 预期:
* 3.0
*/
@InjectProperty(keys = "${full-list}")
public float floatValue;
/**
* keys属性也支持多个通配符,优先级如下:首先通配符的优先级从左到右递减,
* 然后如果通配符被代入List,遵循List中元素index越小优先级越高策略。
*
* 测试用例:
* jaxrstest.jaxrsclient.low-1.a.high-1.b: 1
* jaxrstest.jaxrsclient.low-1.a.high-2.b: 2
* jaxrstest.jaxrsclient.low-2.a.high-1.b: 3
* jaxrstest.jaxrsclient.low-2.a.high-2.b: 4
* 预期:
* 1
*/
@InjectProperty(keys = "${low-list}.a.${high-list}.b")
public long longValue;
/**
* 可以通过注解的defaultValue属性指定默认值。如果字段未关联任何配置属性,
* 定义的默认值会生效,否则默认值会被覆盖。
*
* 测试用例:
* 预期:
* abc
*/
@InjectProperty(defaultValue = "abc")
public String strDef;
}
```
不使用注解:
```Java
public class ConfigNoAnnotation {
/*
* 如果未提供@InjectProperties和@InjectProperty注解,会默认使用字段名作为配置属性名。
* 注意类名不作为前缀起作用。
* 此处将配置属性 strValue 绑定到该字段
*/
public String strValue;
}
```
- 执行注入
使用注解的场景:
```Java
ConfigWithAnnotation config = SCBEngine.getInstance().getPriorityPropertyManager()
.createConfigObject(Configuration.class,
"key", "k",
"low-list", Arrays.asList("low-1", "low-2"),
"high-list", Arrays.asList("high-1", "high-2"),
"full-list", Arrays.asList("l1-1", "l1-2")
);
```
Configuration对象的longValue字段按以下顺序查找已配置的属性:
1. root.low-1.a.high-1.b
2. root.low-1.a.high-2.b
3. root.low-2.a.high-1.b
4. root.low-2.a.high-2.b
Configuration对象的floatValue字段按以下顺序查找已配置的属性:
1. root.l1-1
2. root.l1-2
不使用注解的场景:
```Java
ConfigNoAnnotation config = SCBEngine.getInstance()
.getPriorityPropertyManager().createConfigObject(ConfigNoAnnotation.class);
```
ConfigNoAnnotation 对象的 strValue 字段会查找已配置的属性 strValue,没有前缀和优先级。
注意事项: 2.1.0 之前的版本, 如果系统中存在大量调用createConfigObject的情况, 需要调用
```Java
priorityPropertyManager.unregisterConfigObject(config)
```
进行显示回收。 2.1.0 及其之后的版本, 不需要调用这个接口,系统创建的对象是 WeakReference, 在未被 业务引用以后,会自动回收。
更多关于配置注入的用法,建议下载 java-chassis 的源码, 查看 TestConfigObjectFactory 类里面的示例。
使用Spring 和 Spring Boot的配置机制读取配置
Java Chassis的配置信息,也可以通过Spring和Spring Boot的配置机制进行读取,比如@Value、@ConfigurationProperties等。 Java Chassis
将配置层次应用于Spring Environment中,Spring和Spring Boot读取配置的方式,也能够读取到microservice.yaml
和动态配置的值。