Mybatis技術內幕(2.3.3):反射模塊-Invoker

基於Mybatis-3.5.0版本html

1.0 Invoker執行器

org.apache.ibatis.reflection.invoker.Invoker執行器接口,這裏主要是爲了統一getter方法、setter方法和Field個get和set執行時的差別,使用了對象的適配器模式。代碼和類圖以下:java

/** * 執行器接口:爲了統一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();
}
複製代碼

代碼都比較簡單,就直接上代碼了apache

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 適配器模式

適配器模式下面這篇文章介紹的還不錯:設計模式

《JAVA與模式》之適配器模式緩存

4.0 總結

你們在實際的開發中也能夠巧用一些設計模式,使項目的代碼更加健壯。例如Mybatis反射模塊中,若是這裏不使用適配器模式,那在Reflector中緩存setter和getter的元信息時就不得不使用4個Map分別緩存:getter方法,setter方法、Field-get和Field-set,而且在實際的使用時還要去作if判斷ide

失控的阿甘,樂於分享,記錄點滴this

相關文章
相關標籤/搜索