配置注入提供了一种简单的管理大量复杂配置的机制,开发者不需要使用 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 类里面的示例。