初识mybaits的时候,我还是只小菜鸟,而你也总喜欢找我问问题。而如今我懂了很多,但是找我问问题 的人再也不是你了。

遥想公瑾当年,小乔初嫁了,雄姿英发。
羽扇纶巾,谈笑间,樯橹灰飞烟灭。
春去秋来,公瑾已生华发,吾已不再初年。

mybatis源码我已经下载好了,给大家放到了我的gitee上了,里面可能还有一些理解不到位的地方,请大家多多谅解,也请各位大佬给我提出问题,我好及时改正。

https://gitee.com/studyzhai/mybatis-source-code-analysis.git

那么我们看看mybatis是如何执行的吧

             // 1. 读取配置InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");// 2. 创建SqlSessionFactory工厂SqlSessionFactory sqlSessionFactory = new  SqlSessionFactoryBuilder().build(inputStream);// 3. 获取sqlSessionSqlSession sqlSession = sqlSessionFactory.openSession();// 4. 获取MapperAuthorMapper mapper = sqlSession.getMapper(AuthorMapper.class);List<Author> authors = mapper.selectAllAuthors("1");System.out.println(authors);// 6. 提交事物sqlSession.commit();// 7. 关闭资源sqlSession.close();inputStream.close();

首先我们看第一行代码,就是加载资源文件下的一个文件,mybatis-config.xml这也是mybatis的核心配置文件。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://换成自己的数据库"/><property name="username" value="用户名"/><property name="password" value="密码"/></dataSource></environment></environments><mappers><mapper resource="mappers/AuthorMapper.xml"/></mappers>
</configuration>

这是一个很简单的的配置,就配置了一下数据库的连接,和一个mapper那我们看看mybatis还有那些配置吧!地址:https://mybatis.net.cn/configuration.html 大家自行到官网看。我就不具体描述了。

那么我们回到第一行代码,这个没有啥好说的,就是去加载一个xml配置文件,获取一个输入流。

第二行代码,创建SqlSessionFactory工厂

// 调用重载方法public SqlSessionFactory build(InputStream inputStream) {return build(inputStream, null, null);}public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {try {// 解析mybatis配置文件(mybatis-config.xml)XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);//通过这个方法去解析的mybati核心配置文件return build(parser.parse());} catch (Exception e) {throw ExceptionFactory.wrapException("Error building SqlSession.", e);} finally {ErrorContext.instance().reset();try {inputStream.close();} catch (IOException e) {// Intentionally ignore. Prefer previous error.}}}// 构建SqlSessionFactory工厂public SqlSessionFactory build(Configuration config) {return new DefaultSqlSessionFactory(config);}

1.将读到的流,转化成一个XMLConfigBuilder的对象
2.build方法构建SqlSessionFactory工厂,默认是DefaultSqlSessionFactory
3.parser.parse()方法将核心配置文件,转化成一个大的配置对象,然后交给SqlSessionFactory工厂

配置文件的解析

public Configuration parse() {// 防止配置文件被多次解析if (parsed) {throw new BuilderException("Each MapperConfigParser can only be used once.");}parsed = true;// 解析核心配置文件parseConfiguration(parser.evalNode("/configuration"));return configuration;}// 分别解析root下的每一个根标签private void parseConfiguration(XNode root) {try {// 这些属性就是root标签下可配置的所有属性propertiesElement(root.evalNode("properties")); //issue #117 read properties firsttypeAliasesElement(root.evalNode("typeAliases"));pluginElement(root.evalNode("plugins"));objectFactoryElement(root.evalNode("objectFactory"));objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));settingsElement(root.evalNode("settings"));environmentsElement(root.evalNode("environments"));databaseIdProviderElement(root.evalNode("databaseIdProvider"));typeHandlerElement(root.evalNode("typeHandlers"));// 核心配置文件对应的mappper处理mapperElement(root.evalNode("mappers"));} catch (Exception e) {throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);}}

大家看这些标签和mybatis官网给的配置是不是一一对应,看上面那张图。
具体每个标签如何解析的我就不不墨迹了,大家自己看。这样我们就获取了一个SqlSessionFactory工厂,并且把配置文件封装成一个类传给了工厂。

从工厂中获取sqlSession

 SqlSession sqlSession = sqlSessionFactory.openSession();


大家看这里在上面bulid的时候new 的是一个DefaultSqlSessionFactory工厂,所以这边我们进入DefaultSqlSessionFactory来看一下

 public SqlSession openSession() {return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);}
protected ExecutorType defaultExecutorType = ExecutorType.SIMPLE;

设置默认的执行器是SIMPLE

  /**** @param execType 执行器* @param level  设置事务隔离级别* @param autoCommit  数据库是否自动提交* @return*/private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {Transaction tx = null;try {// 从配置文件种获取使用数据源的环境final Environment environment = configuration.getEnvironment();// 工厂设计模式设置事务管理final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);final Executor executor = configuration.newExecutor(tx, execType);return new DefaultSqlSession(configuration, executor);} catch (Exception e) {closeTransaction(tx); // may have fetched a connection so lets call close()throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);} finally {ErrorContext.instance().reset();}}

那么就从工厂中获取到了SqlSession,并且设置执行器、事务管理、autoCommit

生成代理对象

  AuthorMapper mapper = sqlSession.getMapper(AuthorMapper.class);// 这个地方是在解析配置文件的时候赋值的private Set<Class<?>> knownMappers = new HashSet<Class<?>>();public MapperRegistry(Configuration config) {this.config = config;}// 通过代理生成代理mappper实体public <T> T getMapper(Class<T> type, SqlSession sqlSession) {// 如果这个地方拿不到类类型对于的mapper接口,这个mapper 就没被注册进去 抛出异常结束if (!knownMappers.contains(type))throw new BindingException("Type " + type + " is not known to the MapperRegistry.");try {// 重点代理方法生产代理对象  如果找到了,就去创建对应的代理对象.return MapperProxy.newMapperProxy(type, sqlSession);} catch (Exception e) {throw new BindingException("Error getting mapper instance. Cause: " + e, e);}}// 代理对象的生成/*** 通过jdk动态代理生成对应的代理对象*/@SuppressWarnings("unchecked")public static <T> T newMapperProxy(Class<T> mapperInterface, SqlSession sqlSession) {// 动态代理所必须使用的类加载器ClassLoader classLoader = mapperInterface.getClassLoader();// 这个目前没有看懂为啥是要一个类类型的数组Class<?>[] interfaces = new Class[]{mapperInterface};// 构建mapper代理MapperProxy proxy = new MapperProxy(sqlSession);// 使用jdk动态代理生成代理对象/*** 第一个参数 是一个是类加载器* 的二个是要被代理的接口类类型* 第三个是代理对象 也就是MapperProxy*/return (T) Proxy.newProxyInstance(classLoader, interfaces, proxy); }

关于动态代理的设计模式,我希望大家去学习一下,这个对于我个人而言,是mybais源码中最难的一块了,理解了这个地方其他的就很简单了,那么我们接着往下看,在调用我们的查询方法的时候就会调用

  List<Author> authors = mapper.selectAllAuthors("1");public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if (method.getDeclaringClass() == Object.class) {return method.invoke(this, args);}// 获取接口类final Class<?> declaringInterface = findDeclaringInterface(proxy, method);// 封装 mapperMethod对象final MapperMethod mapperMethod = new MapperMethod(declaringInterface, method, sqlSession);// 执行sqlfinal Object result = mapperMethod.execute(args);if (result == null && method.getReturnType().isPrimitive() && !method.getReturnType().equals(Void.TYPE)) {throw new BindingException("Mapper method '" + method.getName() + "' (" + method.getDeclaringClass() + ") attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");}return result;}

哈哈这就差不多是整个mybatis的设计思路,具体的如何执行的查询,大家可以按着我这个思路往下看看,那么今天的初识mybatis源码就到这里了。

最后把自己的用到的表结构给大家

初识mybatis源码相关推荐

  1. mybatis源码分析之事务管理器

    2019独角兽企业重金招聘Python工程师标准>>> 上一篇:mybatis源码分析之Configuration 主要分析了构建SqlSessionFactory的过程中配置文件的 ...

  2. Mybatis源码解读-设计模式总结

    虽然我们都知道有26个设计模式,但是大多停留在概念层面,真实开发中很少遇到,Mybatis源码中使用了大量的设计模式,阅读源码并观察设计模式在其中的应用,能够更深入的理解设计模式. Mybatis至少 ...

  3. 深入浅出Mybatis系列(三)---配置详解之properties与environments(mybatis源码篇)

    我们通过对mybatis源码的简单分析,可看出,在mybatis配置文件中,在configuration根节点下面,可配置properties.typeAliases.plugins.objectFa ...

  4. MyBatis源码骨架分析

    源码包分析 MyBatis 源码下载地址:https://github.com/MyBatis/MyBatis-3 MyBatis源码导入过程: 下载MyBatis的源码 检查maven的版本,必须是 ...

  5. 深入浅出Mybatis系列(四)---配置详解之typeAliases别名(mybatis源码篇)

    上篇文章<深入浅出Mybatis系列(三)---配置详解之properties与environments(mybatis源码篇)> 介绍了properties与environments, ...

  6. MyBatis源码-解读Executor的三个实现类之BatchExecutor(批处理执行器)

    文章目录 Pre Executor 执行器 接口继承关系 BatchExecutor(重用执行器) 入门小demo 源码 BatchExecutor VS ReuseExecutor Pre MyBa ...

  7. MyBatis源码-解读Executor的三个实现类之SimpleExecutor(简单执行器)

    文章目录 Pre Executor 执行器 接口继承关系 SimpleExecutor(简单执行器) 入门小demo 实例化SimpleExecutor doQuery方法 Pre MyBatis源码 ...

  8. MyBatis源码-深入理解MyBatis Executor的设计思想

    文章目录 Pre JDBC的执行过程 JDBC Demo JDBC Statement 接口 MyBatis执行过程 四大组件 组件之间的关系 Executor 执行器组件 架构总览 接口继承关系 P ...

  9. MyBatis 源码分析系列文章合集

    1.简介 我从七月份开始阅读MyBatis源码,并在随后的40天内陆续更新了7篇文章.起初,我只是打算通过博客的形式进行分享.但在写作的过程中,发现要分析的代码太多,以至于文章篇幅特别大.在这7篇文章 ...

最新文章

  1. jmeter-常见问题及解决方法
  2. 从缓存行出发理解volatile变量、伪共享False sharing、disruptor
  3. (效果一)js实现上拉加载
  4. vscode中配置cmake及debug使用
  5. chorme流程图设计插件gliffy 的加载
  6. 【思维导图】旅行物品清单
  7. 并行计算机未来发展前景
  8. 年薪50万开发者相亲失败:程序员,别输在不会说话上
  9. 【Leetcode】每日一题2021/09/08
  10. 设计模式之代理模式之静态代理
  11. 机器人控制算法一之四轴机械臂正、逆运动学详解
  12. ORA-14400错误
  13. IDEA使用手记——IDEA主菜单恢复
  14. 为何非得选择旧金山测试?通用Cruise讲述无人车炼成记
  15. 英语词性篇 - 英语疑问词
  16. 复杂场景下智能汽车目标检测心得体会
  17. 看得见的实力!传智教育「智能机器人软件开发」课程,打造新型互联网人才!
  18. pomtail 启动失败
  19. 30 道 Vue 面试题,内含详细讲解!
  20. 项目升级到URP遇到的问题

热门文章

  1. Java双亲委派模型:为什么要双亲委派?如何打破它?破在哪里?
  2. (浅谈SOA架构)------SOA架构演变由来
  3. Qt开发的图标登录游戏设计
  4. luov之ImageX 详解,ImageX命令语法
  5. 3D模型【摩天大楼】
  6. jsp实现respond页面的刷新与跳转功能
  7. viper4android mx760,下一个MX500?MX760详尽分析评测+多图。
  8. 【机器学习|数学基础】Mathematics for Machine Learning系列之矩阵理论(23):常数项级数的概念和性质(补充知识)
  9. 安卓手机 python3_python3安卓版下载
  10. java表格界面_Java自学-图形界面 表格