Property常用工具
PropertyTokenizer
PropertyTokenizer主要用来解析类似users[0].age 这样由.和[]组成的表达式
先看一个解析的例子
public static void main(String[] args) {
PropertyTokenizer tokenizer = new PropertyTokenizer("users[0].age");
printInfo(tokenizer);
while (tokenizer.hasNext()) {
tokenizer = tokenizer.next();
printInfo(tokenizer);
}
}
public static void printInfo(PropertyTokenizer tokenizer) {
System.out.println(tokenizer.indexedName);
System.out.println(tokenizer.name);
System.out.println(tokenizer.index);
}
输出结果为
users[0]
users
0
age
age
null
看下源码,以fullname为users[0].age为例
public class PropertyTokenizer implements Iterator<PropertyTokenizer> {
// users
private String name;
// users[0]
private final String indexedName;
// 0
private String index;
// age
private final String children;
// 这里逻辑也很简单
public PropertyTokenizer(String fullname) {
int delim = fullname.indexOf('.');
if (delim > -1) {
name = fullname.substring(0, delim);
children = fullname.substring(delim + 1);
} else {
name = fullname;
children = null;
}
indexedName = name;
delim = name.indexOf('[');
if (delim > -1) {
index = name.substring(delim + 1, name.length() - 1);
name = name.substring(0, delim);
}
}
@Override
public boolean hasNext() {
return children != null;
}
@Override
public PropertyTokenizer next() {
return new PropertyTokenizer(children);
}
@Override
public void remove() {
throw new UnsupportedOperationException("Remove is not supported, as it has no meaning in the context of properties.");
}
}
PropertyTokenizer以.进行分割,并且实现了Iterator接口,可以对.分割的字符串进行迭代解析
PropertyNamer
PropertyNamer主要就是将方法名解析为属性名
public final class PropertyNamer {
private PropertyNamer() {
// Prevent Instantiation of Static Class
}
public static String methodToProperty(String name) {
// 去除方法名前面的get is set
if (name.startsWith("is")) {
name = name.substring(2);
} else if (name.startsWith("get") || name.startsWith("set")) {
name = name.substring(3);
} else {
throw new ReflectionException("Error parsing property name '" + name + "'. Didn't start with 'is', 'get' or 'set'.");
}
// 将去除get set is的剩余内容,第一个字符大写,并且如果第二个字符也是大写字符,那么不会将第一个字符转换成小写字符,比如getUUID,解析出来的属性名称就是UUID
if (name.length() == 1 || (name.length() > 1 && !Character.isUpperCase(name.charAt(1)))) {
name = name.substring(0, 1).toLowerCase(Locale.ENGLISH) + name.substring(1);
}
return name;
}
public static boolean isProperty(String name) {
return isGetter(name) || isSetter(name);
}
public static boolean isGetter(String name) {
return (name.startsWith("get") && name.length() > 3) || (name.startsWith("is") && name.length() > 2);
}
public static boolean isSetter(String name) {
return name.startsWith("set") && name.length() > 3;
}
}
PropertyCopier
PropertyCopier用来对相同类型的两个对象进行属性赋值
public final class PropertyCopier {
private PropertyCopier() {
// Prevent Instantiation of Static Class
}
public static void copyBeanProperties(Class<?> type, Object sourceBean, Object destinationBean) {
Class<?> parent = type;
// 从类的继承层次,从下往上进行属性的赋值
while (parent != null) {
// 获取在当前类中声明的属性
final Field[] fields = parent.getDeclaredFields();
for (Field field : fields) {
try {
try {
field.set(destinationBean, field.get(sourceBean));
} catch (IllegalAccessException e) {
if (Reflector.canControlMemberAccessible()) {
field.setAccessible(true);
field.set(destinationBean, field.get(sourceBean));
} else {
throw e;
}
}
} catch (Exception e) {
// Nothing useful to do, will only fail on final fields, which will be ignored.
}
}
parent = parent.getSuperclass();
}
}
}