基於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屬性分詞器的實現還是很有意思的。大家在實際的開發中如果有類似的業務場景,也可以考慮這樣設計
失控的阿甘,樂於分享,記錄點滴