转载自:
http://hao.jobbole.com/owner/
http://blog.youkuaiyun.com/BestandW1shEs_lsy/article/details/78706790
OWNER是一个Java库,目标是最大限度的减少应用程序中处理properties的代码。
OWNER的主要功能:
• 加载策略:OWNER通过匹配接口类名和properties文件名自动解析并映射;也可以通过注解定制properties文件名。
• 导入properties:另外一种加载properties文件到映射接口的方法。
• 参数化properties:另外一个实用功能,给接口方法提供参数,通过参数配置。
• 类型转换:支持从String类型到基本类型和枚举类型的转换。
• 变量扩展:引用properties中的其他属性。
• 热加载:支持热加载。
• 可访问和可变:可以继承Config的子接口Accessible或者Mutable实现属性的可访问和可变。
• 调试:支持调试功能。
• 禁用功能:可禁用引起问题的功能。
• 配置ConfigFactory:ConfigFactory也是可配置的。
• XML支持:支持XML配置。
• 事件支持:OWNER实现了功能丰富的事件系统,使你知道热加载的发生和属性变化。
• 单例模式:配置信息在一个应用中是单例的。
简单使用:(org.aeonbits.owner:owner-java8:1.0.10)
ServerConfig.java
import org.aeonbits.owner.Config;
@Config.Sources({ "classpath:ServerConfig.properties" })
public interface ServerConfig extends Config {
@Key("server.http.port")
int port();
@Key("server.host.name")
String hostname();
@DefaultValue("42")
int maxThreads();
}
ServerConfig.properties
server.http.port=80
server.host.name=foobar.com
maxThreads=100
测试代码:
import org.aeonbits.owner.ConfigFactory;
public class Test {
public static void main(String[] args) {
ServerConfig config = ConfigFactory.create(ServerConfig.class);
System.out.println(config.port() + "," + config.hostname() + "," + config.maxThreads());
}
}
看例子大概就应该知道如何使用了。
@Sources注解是加载策略,支持classpath和file两种方式,可以接受多了value值,”,”分隔。如果设置多个值时,会按照优先级顺序使用对应的属性文件,即顺序加载属性文件,找到一个文件,其他文件就被忽视。这是因为默认的加载策略是@LoadPolicy(LoadType.FIRST),也可以在@Sources上面使用@LoadPolicy注解来指明其它的加载方式,例如LoadType.MERGE,这种方式是加载所有属性文件,但是优先级顺序读取属性值,第一次获取到属性值后,后面文件中有相同属性就不会再读取。
@DefaultValue的值代表的是该接口方法对应属性的默认值。当接口方法中不能在属性文件中找到对应的属性时,如果没设置默认值,String类型就会返回null,int类型就会报NullPointerException。通过设置默认值,来防止程序报错。
除了使用配置文件还可以采用其它方式来完成类的属性配置。
import org.aeonbits.owner.Config;
public interface ServerConfig1 extends Config {
@Key("server.http.port")
int port();
@Key("server.host.name")
String hostname();
@Key("server.max.threads")
@DefaultValue("42")
int maxThreads();
}
Properties props = new Properties(); // map也可以
props.setProperty("server.http.port", "8080");
props.setProperty("server.host.name", "foobar.com");
props.setProperty("server.max.threads", "100");
ServerConfig1 config1 = ConfigFactory.create(ServerConfig1.class, props);
System.out.println(config1.port() + "," + config1.hostname() + "," + config1.maxThreads());
类型转换:
/*
* 数组和集合的类型转换:
* @Separator与@TokenizerClass可以用在方法上,只影响该方法;也可以用在类上,影响整个类
* @Separator和@TokenizerClass不能在同一级别上使用,否者会抛UnsupportedOperationException
*/
public interface MyConfig extends Config {
@DefaultValue("3.1415")
double pi();
// 默认情况下,OWNER使用逗号","字符为数组和集合标记值
@DefaultValue("apple, pear, orange")
public String[] fruit();
// 用@Separator注释指定不同的字符(和regexp)
@Separator(";")
@DefaultValue("0; 1; 1; 2; 3; 5; 8; 13; 21; 34; 55")
public int[] number();
@DefaultValue("1, 2, 3, 4")
List<Integer> ints();
// 复杂的拆分逻辑可以自定义,使用@TokenizerClass注解
@TokenizerClass(MyTokenizer.class)
@DefaultValue("foo-bar-baz")
public String[] customize();
}
/*
* String[] split(String regex, int limit):limit 参数控制模式应用的次数,因此影响所得数组的长度。
* 如果该限制n大于 0,则模式将被最多应用 n-1次,数组的长度将不会大于n,而且数组的最后一项将包含所有超出最后匹配的定界符的输入。
* 如果n为负,那么模式将被应用尽可能多的次数,而且数组可以是任何长度。
* 如果 n为 0,那么模式将被应用尽可能多的次数,数组可以是任何长度,并且结尾空字符串将被丢弃。
*/
public class MyTokenizer implements Tokenizer{
// 需要复杂的的逻辑可以自定义
public String[] tokens(String values) {
return values.split("-", -1);
}
}
变量扩张:
/*
* 变量扩展:
* 屬性之间的值可以相互使用
*/
public interface ExpandConfig extends Config {
String story();
String animal();
String target();
@Key("target.attribute")
String targetAttribute();
String color();
}
story=The ${animal} jumped over the ${target}
animal=quick ${color} fox
target=${target.attribute} dog
target.attribute=lazy
color=brown
OWNER还实现了重载与热重载,使用Reloadable接口和@HotReload注解来实现,具体使用请参考转载的文章。