基于Mybatis-3.5.0版本
1.0 property包
org.apache.ibatis.reflection.property
包下主要有三个工具类,如下:
2.0 PropertyCopier 属性复制器
org.apache.ibatis.reflection.property.PropertyCopier
属性复制器,主要用于两个对象属性名一致。代码如下:
/**
* 属性复制器
*
* @author Clinton Begin
*/
public final class PropertyCopier {
private PropertyCopier() {
// Prevent Instantiation of Static Class
}
/**
* 将 sourceBean 的属性,复制到 destinationBean 中
* @param type 指定类
* @param sourceBean 来源 Bean 对象
* @param destinationBean 目标 Bean 对象
*/
public static void copyBeanProperties(Class<?> type, Object sourceBean, Object destinationBean) {
Class<?> parent = type;
// 循环,从当前类开始,不断复制到父类,直到父类不存在
while (parent != null) {
// 获得当前 parent 类定义的属性
final Field[] fields = parent.getDeclaredFields();
for (Field field : fields) {
try {
try {
// 从 sourceBean 中,复制到 destinationBean 去
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();
}
}
}
复制代码
2.1 PropertyNamer 属性名工具类
org.apache.ibatis.reflection.property.PropertyNamer
属性名工具类,主要用来处理getter和setter方法。代码如下:
/**
* 属性名工具类,主要用来处理getter和setter方法
* @author Clinton Begin
*/
public final class PropertyNamer {
private PropertyNamer() {
// Prevent Instantiation of Static Class
}
/**
* 根据getter或setter方法获取属性名
* 规则:
* 1.java bean getter/setter 方法命名规范截取属性名
* 2.根据驼峰命名法 将第一个字符小写
* @param name
* @return
*/
public static String methodToProperty(String name) {
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'.");
}
/**
* 如果截取的属性名长度为1或长度大于1且第2位字符是小写
* 例如:
* getA -> A -> a
* getAA -> AA -> AA
*/
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;
}
/**
* 判断是否为is、get、set方法
* @param name 方法名
* @return
*/
public static boolean isProperty(String name) {
return name.startsWith("get") || name.startsWith("set") || name.startsWith("is");
}
/**
* 判断是否为 is、get方法
* @param name 方法名
* @return
*/
public static boolean isGetter(String name) {
return name.startsWith("get") || name.startsWith("is");
}
/**
* 判断是否为set方法
* @param name 方法名
* @return
*/
public static boolean isSetter(String name) {
return name.startsWith("set");
}
}
复制代码
2.2 PropertyTokenizer 属性分词器
org.apache.ibatis.reflection.property.PropertyTokenizer
实现Iterator接口,属性分词器,支持迭代器的访问方式。示例和代码如下:
/**
* 实现 Iterator 接口,属性分词器,支持迭代器的访问方式
*
* @author Clinton Begin
*/
public class PropertyTokenizer implements Iterator<PropertyTokenizer> {
// 当前表达式的名称
private String name;
// 当前表达式的索引名
private final String indexedName;
// 索引下标
private String index;
// 子表达式
private final String children;
/**
* 对传入的表达式,并初始化上面的成员变量
* 例: orders[0].item[0].name
* name = orders
* indexedName =
* orders[0]
* children = item[0].name
* index = 0
*
* @param fullname 待解析的表达式
*/
public PropertyTokenizer(String fullname) {
// 初始化 name、children 字符串,使用 '.'作为分隔
int delim = fullname.indexOf('.');
if (delim > -1) {
name = fullname.substring(0, delim);
children = fullname.substring(delim + 1);
} else {
name = fullname;
children = null;
}
indexedName = name;
// 若存在 '[' ,则获得 index ,并修改 name 。
delim = name.indexOf('[');
if (delim > -1) {
// 截取'['与']'中间的字符串
index = name.substring(delim + 1, name.length() - 1);
// 截取'['之前的字符串
name = name.substring(0, delim);
}
}
public String getName() {
return name;
}
public String getIndex() {
return index;
}
public String getIndexedName() {
return indexedName;
}
public String getChildren() {
return children;
}
@Override
public boolean hasNext() {
return children != null;
}
/**
* 迭代方法 创建一个以children为表达式的PropertyTokenizer对象
*/
@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.");
}
}
复制代码
3.0 总结
这一节的内容比较简单,不过这个PropertyTokenizer属性分词器的实现还是很有意思的。大家在实际的开发中如果有类似的业务场景,也可以考虑这样设计
失控的阿甘,乐于分享,记录点滴