MyBatis源码通~Mapper注册

Mapper接口注册

/mapper节点解析完成后,通过命名空间绑定 mapper 接口,这样才能将映射文件中的 SQL 语句和 mapper 接口中的方法绑定在一起(记录在Configuration的MapperRegistry mapperRegistry),后续即可通过调用 mapper 接口方法执行与之对应的 SQL 语句。

1、入口

XMLMapperBuilder.bindMapperForNamespace

  • 通过namespace全限定名,加载当前Mapper接口(boundType);
  • 记录当前资源已经被加载;
  • 调用Configuration.addMapper(boundType)开始Mapper注册。

2、MapperAnnotationBuilder

在进行Mapper注册的时候,会去扫描解析Mapper上的注解(有时习惯用注解的方式来执行SQL,单单解析XML文件还不够)。Mybatis通过MapperAnnotationBuilder来解析 Mapper 接口上的注解,最后构建MappedStatement对象。

  • 入口方法parse()
    • 加载对应的XML Mapper文件,若在XMLMapperBuilder中已经解析,则不再解析
    • 标记当前Mapper已经被解析
    • 解析@CacheNamespace、@CacheNamespaceRef
    • 遍历Mapper 接口中所有方法上的注解:@Select、@Insert、@Update、@Delete、@SelectProvider、@InsertProvider、@UpdateProvider、@DeleteProvider, 通过方法parseStatement(method)解析并构建MappedStatement对象。(具体的解析逻辑和解析XML文件的逻辑基本一致)

3、Mapper注册中心:MapperRegistry

Mapper接口注册中心,主要用Map来记录,key为Mapper接口,value为MapperProxyFactory代理工厂。

//记录注册的Mapper,可以为Mapper接口,value为Mapper代理工厂
private final Map, MapperProxyFactory> knownMappers = new HashMap<>();

3.1、MapperProxyFactory:Mapper代理类工厂

MapperProxyFactory用于创建Mapper接口对应的代理类MapperProxy。
MyBatis源码通~Mapper注册_第1张图片

public class MapperProxyFactory {

  /**
   * 被代理Mapper接口
   */
private final Class mapperInterface;
public MapperProxyFactory(Class mapperInterface) {
    this.mapperInterface = mapperInterface;
  }
protected T newInstance(MapperProxy mapperProxy) {
    return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
  }

//通过SqlSession创建MapperProxy代理类实例
public T newInstance(SqlSession sqlSession) {
    final MapperProxy mapperProxy = new     MapperProxy<>(sqlSession, mapperInterface, methodCache);
return newInstance(mapperProxy);
  }

3.2、MapperProxy:Mapper接口代理类

实现InvocationHandler接口,代理Mapper接口,分发Sql执行

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    try {
      if (Object.class.equals(method.getDeclaringClass())) {
        return method.invoke(this, args);
      } else if (isDefaultMethod(method)) {
        return invokeDefaultMethod(proxy, method, args);
      }
    } catch (Throwable t) {
      throw ExceptionUtil.unwrapThrowable(t);
    }
    final MapperMethod mapperMethod = cachedMapperMethod(method);
    return mapperMethod.execute(sqlSession, args);
  }

你可能感兴趣的:(MyBatis源码通,MyBatis源码通)