基於Mybatis-3.5.0版本
1.0 Invoker執行器
org.apache.ibatis.reflection.invoker.Invoker
執行器介面,這裡主要是為了統一getter方法、setter方法和Field個get和set執行時的差異,使用了物件的介面卡模式。程式碼和類圖如下:
/**
* 執行器介面:為了統一getter方法、setter方法和Field個get和set執行時的差異
* 物件的介面卡模式
* @author Clinton Begin
*/
public interface Invoker {
/**
* 執行呼叫
* 主要用於執行:getter方法、setter方法和Field個get和set
* @param target 目標
* @param args 引數
* @return 結果
* @throws IllegalAccessException
* @throws InvocationTargetException
*/
Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException;
/**
* @return 類
* 差異:
* 1.getter方法 返回返回型別
* 2.setter方法 返回引數型別
* 3.Field返回自身的型別
*/
Class<?> getType();
}
複製程式碼
程式碼都比較簡單,就直接上程式碼了
2.0 GetFieldInvoker
/**
* Field get屬性執行器
* @author Clinton Begin
*/
public class GetFieldInvoker implements Invoker {
//Field 物件 即被適配者
private final Field field;
public GetFieldInvoker(Field field) {
this.field = field;
}
/**
* 獲取 target Field的屬性值
* 如果Field不可訪問 (訪問許可權不夠),則設定Accessible 強制訪問
*/
@Override
public Object invoke(Object target, Object[] args) throws IllegalAccessException {
try {
return field.get(target);
} catch (IllegalAccessException e) {
if (Reflector.canControlMemberAccessible()) {
field.setAccessible(true);
return field.get(target);
} else {
throw e;
}
}
}
/**
* 返回Field型別
*/
@Override
public Class<?> getType() {
return field.getType();
}
}
複製程式碼
2.1 SetFieldInvoker
/**
* Field set屬性執行器
* @author Clinton Begin
*/
public class SetFieldInvoker implements Invoker {
// Field 物件 即被適配者
private final Field field;
public SetFieldInvoker(Field field) {
this.field = field;
}
/**
* 設定 target Field的屬性值
* 如果Field不可訪問 (訪問許可權不夠),則設定Accessible 強制訪問
*/
@Override
public Object invoke(Object target, Object[] args) throws IllegalAccessException {
try {
field.set(target, args[0]);
} catch (IllegalAccessException e) {
if (Reflector.canControlMemberAccessible()) {
field.setAccessible(true);
field.set(target, args[0]);
} else {
throw e;
}
}
return null;
}
/**
* 返回Field型別
*/
@Override
public Class<?> getType() {
return field.getType();
}
}
複製程式碼
2.2 MethodInvoker
/**
* getter或setter方法執行器
* @author Clinton Begin
*/
public class MethodInvoker implements Invoker {
/**
* getter方法 返回返回型別
* setter方法 返回引數型別
*/
private final Class<?> type;
/**
* Method物件 即被適配者
*/
private final Method method;
public MethodInvoker(Method method) {
this.method = method;
if (method.getParameterTypes().length == 1) {
type = method.getParameterTypes()[0];
} else {
type = method.getReturnType();
}
}
/**
* 執行method物件對應的方法
* 如果method不可訪問 (訪問許可權不夠),則設定Accessible 強制訪問
*/
@Override
public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {
try {
return method.invoke(target, args);
} catch (IllegalAccessException e) {
if (Reflector.canControlMemberAccessible()) {
method.setAccessible(true);
return method.invoke(target, args);
} else {
throw e;
}
}
}
@Override
public Class<?> getType() {
return type;
}
}
複製程式碼
3.0 介面卡模式
介面卡模式下面這篇文章介紹的還不錯:
4.0 總結
大家在實際的開發中也可以巧用一些設計模式,使專案的程式碼更加健壯。例如Mybatis反射模組中,如果這裡不使用介面卡模式,那在Reflector中快取setter和getter的元資訊時就不得不使用4個Map分別取快取:getter方法,setter方法、Field-get和Field-set,並且在實際的使用時還要去做if判斷
失控的阿甘,樂於分享,記錄點滴