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<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<Class<?>, MapperProxyFactory<?>>();

  public MapperRegistry(Configuration config) {
    this.config = config;
  }
   //获取生成的代理对象
  @SuppressWarnings("unchecked")
  public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    //通过Mapper的接口类型 去Map当中查找 如果为空就抛异常
    final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) 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 <T> boolean hasMapper(Class<T> type) {
    return knownMappers.containsKey(type);
  }
  //注册Mapper接口
  public <T> void addMapper(Class<T> 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<T>(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<Class<?>> getMappers() {
    return Collections.unmodifiableCollection(knownMappers.keySet());
  }

  /**
   * @since 3.2.2
   */
  //注册Mapper接口
  public void addMappers(String packageName, Class<?> superType) {
    ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<Class<?>>();
    resolverUtil.find(new ResolverUtil.IsA(superType), packageName);
    Set<Class<? extends Class<?>>> 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 接口对应一个代理工厂。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 前言 主题是Mybatis一级和二级缓存的应用及源码分析。希望在本场chat结束后,能够帮助读者朋友明白以下三点。...
    余平的余_余平的平阅读 5,158评论 0 12
  • 单独使用mybatis是有很多限制的(比如无法实现跨越多个session的事务),而且很多业务系统本来就是使用sp...
    七寸知架构阅读 8,827评论 0 53
  • 再有三四天就过年了,我和姐姐也买好了新衣服,我小心翼翼的拿出衣服,一件一件穿上,反复的照镜子,“姐,好看么?”我满...
    aka杰雨阅读 3,950评论 3 3
  • 前面吉盟财富曾写到网贷行业综合收益率持续下行到10.08%,并且仍有下降的空间,预计下个月或将跌破10%。P2P平...
    吉盟财富公司阅读 1,324评论 0 0
  • 想请问大家,没有什么大学文凭也没有什么技能,之前做销售,漂了几年,觉得去离家较近的城市还是去大城市找工作,我都找了...
    912c9e9498d8阅读 1,513评论 2 2

友情链接更多精彩内容