阅读Mybatis源码很吃力?那是你还不知道阅读套路~

田维常 2020-12-13 13:16:34
java


对于源码,很多人不知道如何看,今天来教教大家如何看源码。
前提是我们需要对整个 Mybatis 的原理、工作流程和模块进行一个整体的直知晓,另外还要有使用经验。
本文主要内容:
 
 

 

源码下载

 

如何下载源码?
进入官网
https://mybatis.org/mybatis-3/zh/index.html
 
 
方法一
跳转到github上,我们可以在github上下源码
https://github.com/mybatis/mybatis-3
 
 
 
 
下载源码
 
 
方法二
也可以通过
https://github.com/mybatis/mybatis-3/releases
下载对应版本jar和源码:
 
 
下载到本地后,解压到自己的本地目录,然后使用eclipse或者IDEA导入。
 
 
发现Mybatis的包目录多大20个,下面我们就来说说这些包的关系和对应的作用。

 

包分成三大类
 
 

 

基础功能包
这些包用来为其他包提供一些外围基础功能,如文件读取功能、反射操作功能等。这些包的特点是功能相对独立,与业务逻辑耦合小。
下面就是基础功能相关的包目录:
 
 

 

配置解析包
这些包用来完成配置解析、存储等工作。这些包中的方法主要在系统初始化阶段运行。
下面就是配置相关的包目录:
 
 

 

核心操作包
这些包用来完成数据库操作。在工作过程中,这些包可能会依赖基础功能包提供的基础功能和配置解析包提供的配置信息。这些包中的方法主要在数据库操作阶段运行。
核心处理层主要做了这四件事:
  1. 把接口中传入的参数解析并映射成JDBC类型;
  2. 解析xml文件中的SQL语句,包括插入参数和动态SQL的生成;
  3. 执行SQL语句;
  4. 处理结果集,并映射成Java对象。
注意:插件也属于核心层,这是由它的工作方式和拦截的对象决定的。
下面就是核心层对应的包目录:
 
 

 

具体包介绍

 

reflection 包
Java 中的反射虽然功能强大,但对大多数开发人员来说,写出高质量的反射代码还是 有一定难度的。
MyBatis 中专门提供了反射模块,该模块对 Java 原生的反射进行了良好的封装,提了更加简洁易用的 API,方便上层调用,并且对反射操作进行了一系列优化,例如缓存了类的元数据,提高了反射操作的性能。
Java反射机制主要提供了以下功能。· 在运行时判断任意一个对象所属的类;· 在运行时构造任意一个类的对象;· 在运行时修改任意一个对象的成员变量;· 在运行时调用任意一个对象的方法。
推荐一篇反射的文章:

 

type 包
① MyBatis 为简化配置文件提供了 别名机制 ,该机制是类型转换模块的主要功能之一。
② 类型转换模块的另一个功能是实现 JDBC 类型与 Java 类型之间的转换,该功能在为 SQL 语句绑定实参以及映射查询结果集时都会涉及:
  • 在为 SQL 语句绑定实参时,会将数据由 Java 类型转换成 JDBC 类型。
  • 而在映射结果集时,会将数据由 JDBC 类型转换成 Java 类型。

 

logging
无论在开发测试环境中,还是在线上生产环境中,日志在整个系统中的地位都是非常重要的。良好的日志功能可以帮助开发人员和测试人员快速定位 Bug 代码,也可以帮助运维人员快速定位性能瓶颈等问题。目前的 Java 世界中存在很多优秀的日志框架,例如 Log4j、 Log4j2、Slf4j 等。
MyBatis 作为一个设计优良的框架,除了提供详细的日志输出信息,还要能够集成多种日志框架,其日志模块的一个主要功能就是 集成第三方日志框架

 

io
资源加载模块,主要是对类加载器进行封装,确定类加载器的使用顺序,并提供了加载类文件以及其他资源文件的功能 。

 

parsing
顾名思义解析器模块,主要提供了两个功能:
  • 一个功能,是对 XPath 进行封装,为 MyBatis 初始化时解析 mybatis-config.xml 配置文件以及映射配置文件提供支持。
  • 另一个功能,是为处理动态 SQL 语句中的占位符提供支持。

 

datasource
数据源是实际开发中常用的组件之一。现在开源的数据源都提供了比较丰富的功能,例如,连接池功能、检测连接状态等,选择性能优秀的数据源组件对于提升 ORM 框架乃至整个应用的性能都是非常重要的。
MyBatis 自身提供了相应的数据源实现,当然 MyBatis 也提供了与第三方数据源集成的接口,这些功能都位于数据源模块之中。

 

transaction
MyBatis 对数据库中的事务进行了抽象,其自身提供了相应的事务接口和简单实现。在很多场景中, MyBatis 会与 Spring 框架集成,并由 Spring 框架管理事务。

 

cache
在优化系统性能时,优化数据库性能是非常重要的一个环节,而添加缓存则是优化数据库时最有效的手段之一。正确、合理地使用缓存可以将一部分数据库请求拦截在缓存这一层。
MyBatis 中提供了一级缓存和二级缓存,而这两级缓存都是依赖于基础支持层中的缓 存模块实现的。这里需要读者注意的是,MyBatis 中自带的这两级缓存与 MyBatis 以及整个应用是运行在同一个 JVM 中的,共享同一块堆内存。如果这两级缓存中的数据量较大, 则可能影响系统中其他功能的运行,所以当需要缓存大量数据时,优先考虑使用 Redis、Memcache 等缓存产品。

 

binding
在调用 SqlSession 相应方法执行数据库操作时,需要指定映射文件中定义的 SQL 节点,如果出现拼写错误,我们只能在运行时才能发现相应的异常。为了尽早发现这种错误,MyBatis 通过 Binding 模块,将用户自定义的 Mapper 接口与映射配置文件关联起来,系统可以通过调用自定义 Mapper 接口中的方法执行相应的 SQL 语句完成数据库操作,从而避免上述问题。
值得读者注意的是,开发人员无须编写自定义 Mapper 接口的实现,MyBatis 会自动为其创建动态代理对象。在有些场景中,自定义 Mapper 接口可以完全代替映射配置文件,但有的映射规则和 SQL 语句的定义还是写在映射配置文件中比较方便,例如动态 SQL 语句的定义。

 

annotations
随着 Java 注解的慢慢流行,MyBatis 提供了 注解 的方式,使得我们方便的在 Mapper 接口上编写简单的数据库 SQL 操作代码,而无需像之前一样,必须编写 SQL 在 XML 格式的 Mapper 文件中。虽然说,实际场景下,大家还是喜欢在 XML 格式的 Mapper 文件中编写相应的 SQL 操作。

 

exceptions
exceptions包中有三个与Exception相关的类:
  • IbatisException类(已经设置为不推荐使用了)、
  • PersistenceException类
  • TooManyResultsException类
在 MyBatis的其他包中,还有许多异常类。这些异常类中除 RuntimeSqlException类外,均为 PersistenceException的子类。
MyBatis中异常类类图:
 
 
几乎每个都有阈值对应的自定义异常。

 

scripting
拼凑 SQL 语句是一件烦琐且易出错的过程,为了将开发人员从这项枯燥无趣的工作中 解脱出来,MyBatis 实现 动态 SQL 语句 的功能,提供了多种动态 SQL语句对应的节点。例如 <where> 节点、 <if> 节点、 <foreach> 节点等 。通过这些节点的组合使用, 开发人 员可以写出几乎满足所有需求的动态 SQL 语句。
MyBatis 中的 scripting 模块,会根据用户传入的实参,解析映射文件中定义的动态 SQL 节点,并形成数据库可执行的 SQL 语句。之后会处理 SQL 语句中的占位符,绑定用户传入的实参。

 

plugin
Mybatis 自身的功能虽然强大,但是并不能完美切合所有的应用场景,因此 MyBatis 提供了插件接口,我们可以通过添加用户自定义插件的方式对 MyBatis 进行扩展。用户自定义插件也可以改变 Mybatis 的默认行为,例如,我们可以拦截 SQL 语句并对其进行重写。
由于用户自定义插件会影响 MyBatis 的核心行为,在使用自定义插件之前,开发人员需要了解 MyBatis 内部的原理,这样才能编写出安全、高效的插件。

 

session 包
接口层相对简单,其核心是 SqlSession 接口,该接口中定义了 MyBatis 暴露给应用程序调用的 API,也就是上层应用与 MyBatis 交互的桥梁。接口层在接收到调用请求时,会调用核心处理层的相应模块来完成具体的数据库操作。

 

executor包
主要负责维护一级缓存和二级缓存,并提供事务管理的相关操作,它会将数据库相关操作委托给 StatementHandler完成。

 

mapping包
mapping主要是SQL操作解析后的映射

 

builder包
builder是配置和注解的解析过程。

 

cursor包
处理游标相关的代码。实话实说,工作中用到很少,所以这里就不展开介绍。

 

jdbc
生成JDBC能处理的语句 。

 

lang包
指定使用Java7还是Java8的API的注解。
 
 

 

总结
面对如何看源码,很多人都无从下手,有的人也是瞎搞,到最后肯定看一点点就放弃了。
对于看源码的套路,个人建议:
1.学会使用,必须要熟练使用;
2.先掌握一些常见的设计模式(工厂模式、单列模式、模板方法模式、装饰器模式、代理模式等);
3.熟悉设计原理;
4.熟悉源代码的这个包目录,以及每个包的大致功能;
5.多思考为什么是这样;
6.王者模式:既然你会用了,那么如果让你来设计,你会怎么设计?
版权声明
本文为[田维常]所创,转载请带上原文链接,感谢
https://my.oschina.net/u/4728925/blog/4794688

  1. Linux阅码场 - Linux内核月报(2020年10月)
  2. 宋宝华:为什么Linux内核常常用unsigned long来代替指针
  3. A cup of wine with peach, plum and spring breeze
  4. In depth exploration of Linux kprobe mechanism
  5. In depth understanding of Linux remote procedure call (RPC) online video course
  6. Early bird Countdown: a simple introduction to Linux kernel module online video course
  7. In depth analysis of Linux kernel reverse mapping mechanism
  8. Introduction of Linux file system and persistent memory
  9. Linux reading yard - Linux kernel monthly report (October 2020)
  10. Song Baohua: why does Linux kernel often use unsigned long instead of pointer
  11. JAVA NIO 不是同步非阻塞I/O吗,为什么说JAVA NIO提供了基于Selector的异步网络I/O?
  12. Isn't Java NiO synchronous and non blocking I / O? Why does Java NiO provide asynchronous network I / O based on selector?
  13. Java 生成随机数的 5 种方式,你知道几种?
  14. Spring中毒太深,离开Spring我居然连最基本的接口都不会写了
  15. Java安全之原生readObject方法解读
  16. How many ways do you know to generate random numbers in Java?
  17. ConcurrentHashMap源码逐行解析
  18. Spring is so poisoned that I can't even write the most basic interface without spring
  19. Interpretation of native readObject method in Java Security
  20. Concurrent HashMap source code parsing line by line
  21. Qt-解决Qt与MySQL连接过程中出现“QSqlDatabase: QMYSQL driver not loaded”问题
  22. Oracle 字符集常见字符集及解决方案
  23. 程序员漫画:成人的数据结构
  24. ConcurrentHashMap(细节篇)
  25. 一文让你彻底了解Redis(进阶),史上最全,不看后悔!!!【建议收藏】
  26. 03-Debezium的载体Kafka Connect
  27. 三面阿里(支付宝)Java高开岗,疫情期间复习两月有幸拿到offer
  28. QT - solve the problem of "QSqlDatabase: qmmysql driver not loaded" during the connection between QT and mysql
  29. Oracle character set common character set and solution
  30. Programmer's cartoon: adult's data structure
  31. Concurrent HashMap (details)
  32. Let you thoroughly understand redis (Advanced), the most complete in history, do not look regret!!! [suggested collection]
  33. Kafka connect vector of 03 debezium
  34. Three faces Ali (Alipay) Java Gao Gang Kong, during the epidemic review two months, was lucky to get offer
  35. 好消息,在win10上也可以运行Linux了,详细操作教程送给你
  36. Good news, can also run Linux on win10, detailed operation tutorial for you
  37. Redis 的 8 大数据类型,写得非常好!
  38. Redis's 8 major data types are well written!
  39. 重磅!Kubernetes决定弃用Docker
  40. Heavy weight! Kubernetes decided to abandon docker
  41. SpringCloud中Zuul网关原理及其配置,看它就够了!
  42. 反射调用Java层方法
  43. Spring cloud zuul gateway principle and configuration, it is enough to see it!
  44. Reflection calls Java layer methods
  45. 【SpringBoot】SpringMVC自动配置
  46. 【SpringBoot】国际化
  47. 使用OpenSSL自建一个HTTPS服务
  48. [springboot] automatic configuration of spring MVC
  49. 给DELL外星人笔记本安装ArchLinux系统
  50. [springboot] internationalization
  51. Using OpenSSL to build an HTTPS service
  52. Installing archlinux for Dell alien laptop
  53. 【重学 JavaScript】 - 作用域和闭包
  54. Re learn JavaScript - scope and closure
  55. 最简单的 Go Dockerfile 编写姿势,没有之一!
  56. The simplest go dockerfile writing posture, no one!
  57. 15分钟搭建RocketMQ源码调试环境
  58. JavaScript小案例-阶乘!
  59. Build rocketmq source code environment for 15 minutes
  60. JavaScript case - factorial!