转载

Mybatis源码系列(二)Mybatis获取Mapper的过程

  • mybatis加载mapper的代码
  • 具体实例化Mapper的过程
  • 总结

mybatis加载mapper的代码

//前置加载配置文件省略  
//实际上获取的是DefaultSqlSessionFactory 具体为何可以看对应的build方法
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//得到DefaultSqlSession
SqlSession session = sqlSessionFactory.openSession();
//通过DefaultSqlSession获取mapper
UserMapper mapper = session.getMapper(UserMapper.class);
复制代码

具体实例化Mapper的过程

因为 UserMapper mapper = session.getMapper(UserMapper.class) 在创建SqlSession的时候实际上创建的是DefaultSqlSession,所以我们直接进入到DefaultSqlSession的对应getMapper方法中:

//org.apache.ibatis.session.defaults.DefaultSqlSession#getMapper(Class<T> type)
@Override
public <T> T getMapper(Class<T> type) {
  return configuration.<T>getMapper(type, this);
}
复制代码

从代码中我们能够看到,实际上获取的是 org.apache.ibatis.session.Configuration#getMapper(Class<T> type, SqlSession sqlSession) 这个方法,那么现在我们进到对应的方法中看一下:

//org.apache.ibatis.session.Configuration#getMapper(Class<T> type, SqlSession sqlSession)
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
   return mapperRegistry.getMapper(type, sqlSession);
 }
复制代码

能够清楚的看到,这个方法实际上调用的是 org.apache.ibatis.binding.MapperRegistry#getMapper(Class<T> type, SqlSession sqlSession) 这个方法,继续查看对应的方法内容

//org.apache.ibatis.binding.MapperRegistry#getMapper(Class<T> type, SqlSession sqlSession)
@SuppressWarnings("unchecked")
  public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    //获取对应类型的代理工厂
   final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
  //不存在直接抛出异常
   if (mapperProxyFactory == null) {
      throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
    }
   try {
      //存在代理工厂生成代理对象
      return mapperProxyFactory.newInstance(sqlSession);
    } catch (Exception e) {
      throw new BindingException("Error getting mapper instance. Cause: " + e, e);
    }
  }
复制代码

我们能够看到,重点的代码实现是在 mapperProxyFactory.newInstance(sqlSession); 所以我们现在进入 org.apache.ibatis.binding.MapperProxyFactory#newInstance(org.apache.ibatis.session.SqlSession) 这个方法中:

//org.apache.ibatis.binding.MapperProxyFactory#newInstance(org.apache.ibatis.session.SqlSession)
public T newInstance(SqlSession sqlSession) {
    final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
    return newInstance(mapperProxy);
  }
复制代码

通过 newInstance(mapperProxy) ,找到了类中的另一个方法 org.apache.ibatis.binding.MapperProxyFactory#newInstance(org.apache.ibatis.binding.MapperProxy<T>) ,代码如下:

//org.apache.ibatis.binding.MapperProxyFactory#newInstance(org.apache.ibatis.binding.MapperProxy<T>)
 @SuppressWarnings("unchecked")
  protected T newInstance(MapperProxy<T> mapperProxy) {
    //代理生成的过程
    return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
  }
复制代码

具体 org.apache.ibatis.binding.MapperProxy 类的内容,这一次先不看,下一次在查看具体调用流程的时候再讲。

总结

通过源码的调用过程,我们知道在mybatis中获取对应的Mapper的时候,其实获取的是一个代理( 代理不太懂的,可以网上找相关的博文,挺多的,这一点儿就不仔细说了 ),但是在拿到这个代理之后,mybatis到底做了什么事情,下一篇继续,至于mybatis的SqlSessionFactory的初始化过程,咱们再等等,放到后面再说。

原文  https://juejin.im/post/5ea64b5b51882573c508f494
正文到此结束
Loading...