【Mybatis】【SQL执行过程】【一】Mybatis源码解析-Mapper代理产生过程

1  前言

上节我们分析了配置文件的详细解析以及Mapper的详细解析,可以看作都是静态的东西,那么这节开始我们就要看动的东西,我们就来看看 SQL 的执行过程,我们平时都会写 Mapper接口,那么这节我们先来看下我们的 Mapper 接口的代理创建过程。

2  源码分析

2.1  Mapper 接口放哪了

我们先来简单回顾下我们的 Mapper接口信息在解析的过程中是存放到了哪里,可以看到是放进了 Configurtion的 MapperRegistry对象的 knownMappers中了。

2.2  Mapper 接口代理创建

2.2.1  创建时机

那么我们的代理是什么时候创建的呢?

@SneakyThrows
public static void main(String[] args) throws IOException {
  // 配置文件创建 io
  InputStream reader = Resources.getResourceAsStream("config.xml");
  // 创建配置文件构建器
  XMLConfigBuilder builder = new XMLConfigBuilder(reader, null, null);
  // 解析我们的配置文件生成 configuration 对象
  Configuration configuration = builder.parse();
  // 根据 configuration 创建我们的 SqlSessionFactory (sqlSession工厂)
  SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
  // 有了工厂我们就可以拿会话了,会话可以看作就是连接,有了连接我们就能执行 sql
  SqlSession sqlSession = sqlSessionFactory.openSession();
  // 获取我们的 mapper接口类
  OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);
  System.out.println(orderMapper);
  OrderPo one = orderMapper.getOne();
  System.out.println(one);
}

是不是就是我们从 SqlSession 中获取某个 Mapper的时候创建的呢?是的哈

2.2.2  创建代理

那我们从 sqlSession.getMapper(OrderMapper.class),出发看一下我们的代理创建的过程:

/**
 * DefaultSqlSession
 * 要知道每个 SqlSession 里边都有个 Configuration哈
 */
@Override
public <T> T getMapper(Class<T> type) {
  // 从 configuration 中获取
  return configuration.getMapper(type, this);
}
// Configuration
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
  return mapperRegistry.getMapper(type, sqlSession);
}
// MapperRegistry
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
  // 看获取到我们解析式时,放进去的 Mapper信息
  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 创建的,并且把当前的 SqlSession 对象作为参数传了进去,那么我们继续看下 MapperProxyFactory 创建代理的过程:

// MapperProxyFactory
public T newInstance(SqlSession sqlSession) {
  /**
   * 创建 MapperProxy 对象
   * sqlSession 就是我们当前的 SqlSession
   * mapperInterface 就是我们 mapper接口的全类名
   * methodCache 缓存
   */
  final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);
  return newInstance(mapperProxy);
}
protected T newInstance(MapperProxy<T> mapperProxy) {
  // 可以看到是用的我们的 JDK 动态代理创建的代理类
  return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}

可以看到是用JDK动态代理创建的 Mapper接口的代理类,并且增强的逻辑就是 MapperProxy类,当我们调用 Mapper接口的方法时,就会进入到 MapperProxy的 invoke方法了是不是,就会执行咯,关于执行的内容比较多,我们单独写一篇哈,下节见。

3  小结

好了,这节我们简单回顾了下 Mapper 接口的解析存放以及代理的入口和创建代理的过程,下节我们讲解下实际的执行过程哈,有理解不对的地方欢迎指正哈。

posted @ 2023-03-06 07:20  酷酷-  阅读(44)  评论(0编辑  收藏  举报