聊聊 mybatis 的反射之 Invoker 模块
上篇文章中我们介绍了 mybatis 的 Reflector 的构造方法,深入源码分析了一波,并了解到对于属性的 getter setter 方法封装成 map 集合中,key 是属性名,value 是 MethodInvoker,没有 getter setter 方法的属性也是封装到了 map 中,key 是属性名,value 是 GetFieldInvoker 和 SetFieldInvoker,他们都是 Invoker 接口的实现类,下面看一下 Invoker 接口:
public interface Invoker {
//调用
Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException;
//取得类型
Class<?> getType();
}
复制代码
接口比较简单,只有两个方法:调用和获取类型,MethodInvoker, GetFieldInvoker ,SetFieldInvoker 这三个类都实现了 Invoker 接口,MethodInvoker 重写了 invoke 方法,方法中就是直接调用 Method.invoke 方法
MethodInvoker
public class MethodInvoker implements Invoker {
private Class<?> type;
private Method method;
public MethodInvoker(Method method) {
this.method = method;
if (method.getParameterTypes().length == 1) {
type = method.getParameterTypes()[0];
} else {
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;
}
}
复制代码
通过构造方法的逻辑,我们知道如果只有一个参数,返回参数类型,否则返回 return 的类型,在调用方法中直接调用了 Method.invoke()方法
GetFieldInvoker
GetFieldInvoker 是 Field 作为成员变量,invoke 调用方法中直接调用 field.get(target)方法,获取类型的时候也直接使用 field.getType()方法来进行获取
public class GetFieldInvoker implements Invoker {
private Field field;
public GetFieldInvoker(Field field) {
this.field = field;
}
//就是调用Field.get
@Override
public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {
return field.get(target);
}
@Override
public Class<?> getType() {
return field.getType();
}
}
复制代码
对于其他的 Invoker 的接口这里不再一一分析了,整体逻辑都是很简单的。
ReflectorFactory
另外,ReflectorFactory 是一个工厂接口,它的默认实现类是 DefaultReflectorFactory
接口:
public interface ReflectorFactory {
boolean isClassCacheEnabled();
void setClassCacheEnabled(boolean classCacheEnabled);
Reflector findForClass(Class<?> type);
}
复制代码
这里定义三个方法
而 DefaultReflectorFactory 实现类的代码如下:
public class DefaultReflectorFactory implements ReflectorFactory {
private boolean classCacheEnabled = true;
private final ConcurrentMap<Class<?>, Reflector> reflectorMap = new ConcurrentHashMap<>();
public DefaultReflectorFactory() {
}
@Override
public boolean isClassCacheEnabled() {
return classCacheEnabled;
}
@Override
public void setClassCacheEnabled(boolean classCacheEnabled) {
this.classCacheEnabled = classCacheEnabled;
}
/**
* 生产Reflector对象
* @param type 目标类型
* @return 目标类型的Reflector对象
*/
@Override
public Reflector findForClass(Class<?> type) {
if (classCacheEnabled) { // 允许缓存
// 生产入参type的反射器对象,并放入缓存
return reflectorMap.computeIfAbsent(type, Reflector::new);
} else {
return new Reflector(type);
}
}
}
复制代码
DefaultReflectorFactory 中有一个 ConcurrentHashMap 成员变量,使用 ConcurrentHashMap 来做缓存,缓存的是 class 对应的 Reflector 对象信息,在允许进行缓存的情况下,会将入参 type 和对应的反射器对象放入到缓存中
总结
这篇文章主要讲解了 Invoker 接口和它实现类 GetFieldInvoker,以及 ReflectorFactory 接口和它的默认实现类,Invoker 接口主要是用来更加 Class 类来生成 MethodInvoker, GetFieldInvoker ,SetFieldInvoker 具体对象信息的并保存在 map 中供其他方法使用,ReflectorFactory 是主要是用于 Reflector 对象的缓存,它的默认实现类是 DefaultReflectorFactory,缓存是利用的 ConcurrentHashMap 来进行缓存的,希望看完这篇文章让你对 Mybatis 的反射模块有所帮助
评论