Mybatis源码中,binding包下的类都是用来进行Mapper的映射以及方法的映射,包下有MapperProxy、MapperMethod等类。
MapperProxy
解析mybatis-config.xml类时,会获取到mappers标签中属性对应的包名,获取该包下所有的接口,并将接口都放到MapperRegistry中的knownMappers(Map<Class<?>, MapperProxyFactory<?>> knownMappers)集合中去,在调用getMapper()进行动态代理创建类时,从knowMappers中获取到Class对应的MapperProxyFactory,根据MapperProxyFactory创建出MapperProxy,调用newInstance动态代理创建对象。
public class MapperRegistry {
// 记录了Mapper接口与对应MapperProxyFactory之间的关系
private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<>();
public <T> void addMapper(Class<T> type) {
// 检测type是否为接口
if (type.isInterface()) {
// 检测是否已经加载过该接口
if (hasMapper(type)) {
throw new BindingException("Type " + type + " is already known to the MapperRegistry.");
}
boolean loadCompleted = false;
try {
// 将Mapper接口对应的Class对象和MapperProxyFactory对象添加到knownMappers集合
knownMappers.put(type, new MapperProxyFactory<>(type));
// It's important that the type is added before the parser is run
// otherwise the binding may automatically be attempted by the
// mapper parser. If the type is already known, it won't try.
MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);
parser.parse();
loadCompleted = true;
} finally {
// 如果加载过程中出现异常需要再将这个mapper从mybatis中删除
if (!loadCompleted) {
knownMappers.remove(type);
}
}
}
}
}
//省略部分代码....
MapperMethod
MapperMethod对象,会在getMapper()创建对象后,执行具体方法时,进行构建。调用构造方法的同时,还会同时创建SqlCommand和MethodSignature。
public class MapperMethod {
// 记录了SQL语句的名称和执行SQL语句的类型
private final SqlCommand command;
// SQL方法返回类型和参数名。
private final MethodSignature method;
public MapperMethod(Class<?> mapperInterface, Method method, Configuration config) {
this.command = new SqlCommand(config, mapperInterface, method);
this.method = new MethodSignature(config, mapperInterface, method);
}
}