[MyBatis源码分析 - 反射器模块 - 组件二] Invo
2020-10-17 本文已影响0人
小胡_鸭
一、简介
Invoker 是一个接口,其实现类有 MethodInvoker、SetFieldInvoker、GetFieldInvoker,关系如下:
Invoker 接口中定义了两个方法,分别用来执行反射调用和获取属性类型,源码如下:
public interface Invoker {
/**
* 执行调用
* @param target 被反射调用的目标
* @param args 参数
* @return
* @throws IllegalAccessException
* @throws InvocationTargetException
*/
Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException;
// 类
Class<?> getType();
}
二、MethodInvoker
对于有 getter/setter 方法的属性,使用的是 MethodInvoker 封装了 Method 对象,其 invoke() 方法是通过调用 Method.invoke() 方法实现的,获取属性类型时,通过判断方法是否带参数,分别获取参数类型和方法返回值作为属性类型,源码如下:
public class MethodInvoker implements Invoker {
private Class<?> type;
private Method method;
public MethodInvoker(Method method) {
this.method = method;
// 获取属性类型,如果是setter方法,参数个数为1,属性类型为参数类型
if (method.getParameterTypes().length == 1) {
type = method.getParameterTypes()[0];
} else {
// 如果是getter方法,属性类型为方法的返回值
type = method.getReturnType();
}
}
// 通过调用Method.invoke()执行目标对象方法
@Override
public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {
return method.invoke(target, args);
}
@Override
public Class<?> getType() {
return type;
}
}
三、SetFieldInvoker & GetFieldInvoker
没有 getter/setter 方法的属性,使用 GetFieldInvoker、SetFieldInvoker 封装了属性对应的 Field 对象,通过调用 Field.get()/set() 实现获取设置属性值。
public class GetFieldInvoker implements Invoker {
// 属性对应的Field对象
private Field field;
public GetFieldInvoker(Field field) {
this.field = field;
}
// 获取目标对象的属性值
@Override
public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {
return field.get(target);
}
// 获取属性类型
@Override
public Class<?> getType() {
return field.getType();
}
}
public class SetFieldInvoker implements Invoker {
// 属性对应的Field对象
private Field field;
public SetFieldInvoker(Field field) {
this.field = field;
}
// 设置目标对象的属性值
@Override
public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {
field.set(target, args[0]);
return null;
}
// 获取属性类型
@Override
public Class<?> getType() {
return field.getType();
}
}
四、总结
对应 Reflector 对象来说,解析类元信息时,需要根据属性是否有对应的 getter/setter 方法来决定使用 Invoker 接口的哪个实现类,对于使用 Reflector 的代码来说,只需要知道其 getMethods、setMethods 集合中的值为 Invoker 对象,调用该对象可实现获取设置属性值即可。