【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 接口的解析存放以及代理的入口和创建代理的过程,下节我们讲解下实际的执行过程哈,有理解不对的地方欢迎指正哈。