拜托别再问我Mybatis-66个类手撸一个Mybatis

本文概述了Mybatis的底层执行流程,从SqlSessionFactory的创建,通过配置文件解析,到Mapper的获取和执行,涉及环境配置、Mapper映射、PreparedStatement处理等关键环节。
摘要由CSDN通过智能技术生成

前言

之前出了一套《吃透Mybatis源码》,本篇文章是整体性的概括一下Mybatis的底层实现流程,以《66个类手撸Mybatis》为基础进行讲解,代码已经上传到Gitee,希望对你有所帮助

架构说明

cg-mybatis
- cg-mybatis-core : mybatis 核心
- cg-mybatis-example : 测试用例

在这里插入图片描述
下面是Mybatis源码执行大致流程图

// 创建 SqlSessionFactoryBuilder 对象
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();

// 通过核心配置文件所对应的字节输入流创建工厂类 SqlSessionFactory ,生产SqlSession 对象
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build("mybatis-config.xml");

SqlSession sqlSession = sqlSessionFactory.openSession(true);

UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

User user = userMapper.selectById(1L);

Mybatis底层执行原理图
在这里插入图片描述

源码说明

1.加载配置

1.1. 当我们执行 sqlSessionFactoryBuilder.build 的时候,SQLSessionFactoryBuilder底层会加载Mybatis配置文件和解析Mapper.xml 映射文件。底层通过Resource以InputStream的方式加载资源文件,执行XmlConfigBuilder#parse进行配置文件的解析

1.2. XmlConfigBuilder#parse 方中会通过XPathParser解析Mybatis的配置文件,解析其中的配置,比如:properties,settings,typeAliases,plugins等等,这里重点说一下:environments和mappers

1.3. 对于environments而言主要是会得到:transactionManager事务管理器,和 DataSourceFactory 数据源,然后都会封装到 Environment,再设置给一个:Configuration 对象(Mybatis核心配置对象,里面维护了Mybatis各种核心组件,比如:别名,mapper, TypeHandler等等都会在里面)

1.4. 除此之外还会解析mappers映射文件通过 XmlMapperBuilder进行解析,解析好之后会得到:MapperRegistry(维护Mapper映射器生成jdk代理),TypeHandler(类型处理),MappedStatement(SQL语句的封装),ResultMap(结果映射),typeAliasRegistry(维护别名)等等。这些东西都会封装到Confuration对象中,并创建一个 DefaultSqlSessionFactory对象把Configuration交给该工厂

2.获取SqlSession

在执行DefaultSqlSessionFactory#openSession的时候,底层会创建好Executor执行器,并把执行器和Configuration设置给DefaultSqlSession对象,并发返回DefaultSqlSession

3.获取Mapper

当执行sqlSession.getMapper的时候,会从Configuration的MapperRegistry中根据Mapper的类型获取Mapper实例。底层会通过 MapperProxyFactory来创建Mapper,用到了JDK动态代理,MapperProxy中是增强逻辑。

4.执行Mapper

1.在执行Mapper方法的时候代码会来到 MapperProxy#invoke方法中,方法中会构建一个 MapperMethod去执行,会根据SQL的类型做不通的执行,比如:是select查询就会走SqlSession#selectOne,该方法底层使用的是SqlSession#selectList方法。

2.selectList方法中会调用executor.query去执行,方法中会找到对应的语句对象MappedStatement,参数:parameter,结果处理器ResultHandler等,executor有很多种,通过委派进行调用。

3.然后就是 通过Configuration创建一个 PreparedStatementHandler,通过该hander去创建一个PreparedStatement,并为其设置好参数,SQL也会把参数替换为 “?”。

4.然后就是调用PreparedStatementHandler#query去执行PreparedStatement,这里比较简单就是执行PreparedStatement#execute方法(JDBC的内容)。

5.接下来就是调用 ResultHandler#handleResultSets去处理执行的结果了,结果处理方案是从 PreparedStatement中拿到ResultSet,然后从ResultMap中拿到ResultType,调用:ObjectFactory#create方法根据ResultType创建结果对象的实例(反射)。再通过反射拿到对象的Field,拿到ResultSet中对应的值,通过反射给Field赋值,字段的类型会通过jdbcType来处理。

6.最后把结果对象转到List里面进行返回,如果是selectOne,就会取list中的第0个元素返回。

总结

相比Spring来说Mybatis的源码是相对简单的,你可以通过上面的源码去深入理解Mybatis核心机制,当然这里的源码只是实现了简单的单个对象查询,时间关系其中很多细节是没有去实现的,但是毫不影响你对Mybatis的理解或者用于面试吊打面试官了。建议你对着图多看几遍。

  • 34
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

墨家巨子@俏如来

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值