Mybatis:Mapper接口编程原理分析(二)

在上一篇 Mybatis:Mapper接口编程原理分析(一)中,Mapper 接口最后向MapperRegistry 注册。MapperRegistry 它是用来注册 Mapper 接口和获取 Mapper 接口代理类实例的工具类,完成这两个工作是通过 getMapper 方法和 addMapper 方法。
它的源码如下:

//注册Mapper接口与获取生成代理类实例的工具类
public class MapperRegistry {
    
  //全局配置文件对象
  private final Configuration config;
  
  //一个HashMap Key是mapper的类型对象, Value是MapperProxyFactory对象
  //这个MapperProxyFactory是创建Mapper代理对象的工厂 
  private final Map, MapperProxyFactory> knownMappers = new HashMap, MapperProxyFactory>();

  public MapperRegistry(Configuration config) {
    this.config = config;
  }
   //获取生成的代理对象
  @SuppressWarnings("unchecked")
  public  T getMapper(Class type, SqlSession sqlSession) {
    //通过Mapper的接口类型 去Map当中查找 如果为空就抛异常
    final MapperProxyFactory mapperProxyFactory = (MapperProxyFactory) knownMappers.get(type);
    if (mapperProxyFactory == null) {
      throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
    }
    try {
      //否则创建一个当前接口的代理对象 并且传入sqlSession
      return mapperProxyFactory.newInstance(sqlSession);
    } catch (Exception e) {
      throw new BindingException("Error getting mapper instance. Cause: " + e, e);
    }
  }
  
  public  boolean hasMapper(Class type) {
    return knownMappers.containsKey(type);
  }
  //注册Mapper接口
  public  void addMapper(Class type) {
    if (type.isInterface()) {
      if (hasMapper(type)) {
        throw new BindingException("Type " + type + " is already known to the MapperRegistry.");
      }
      boolean loadCompleted = false;
      try {
        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 {
        if (!loadCompleted) {
          knownMappers.remove(type);
        }
      }
    }
  }

  /**
   * @since 3.2.2
   */
  public Collection> getMappers() {
    return Collections.unmodifiableCollection(knownMappers.keySet());
  }

  /**
   * @since 3.2.2
   */
  //注册Mapper接口
  public void addMappers(String packageName, Class superType) {
    ResolverUtil> resolverUtil = new ResolverUtil>();
    resolverUtil.find(new ResolverUtil.IsA(superType), packageName);
    Set>> mapperSet = resolverUtil.getClasses();
    for (Class mapperClass : mapperSet) {
      addMapper(mapperClass);
    }
  }

  /**
   * @since 3.2.2
   */
  //通过包名扫描下面所有接口
  public void addMappers(String packageName) {
    addMappers(packageName, Object.class);
  }
}

从源码可知,Mapper 接口只会被加载一次,然后缓存在 HashMap 中,其中 key 是 mapper 接口类对象,value 是 mapper 接口对应的 代理工厂。需注意的是,每个 mapper 接口对应一个代理工厂。

你可能感兴趣的:(Mybatis:Mapper接口编程原理分析(二))