Mybatis技术内幕(2.3.2):反射模块-Invoker

基于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 适配器模式

适配器模式下面这篇文章介绍的好不错:

《JAVA与模式》之适配器模式

4.0 总结

大家在实际的开发中也可以巧用一些设计模式,使得项目的代码更加健壮。例如Mybatis反射模块中,如果这里不使用适配器模式,那在Reflector中缓存setter和getter的元信息时就不得不使用4个Map分别取缓存:getter方法,setter方法、Field-get和Field-set,并且在实际的使用时还要去做if判断

失控的阿甘,乐于分享,记录点滴

猜你喜欢

转载自juejin.im/post/5c8f669b5188252d8f630450
今日推荐