likes
comments
collection
share

谈一谈初学者该如何快速入门Mybatis源码

作者站长头像
站长
· 阅读数 7

思考,输出,沉淀。用通俗的语言陈述技术,让自己和他人都有所收获。 作者:毅航😜


前言

可以说,目前市面上流行的任意一款框架其都必然存在对应输入/输出的逻辑。换言之,只要我们知晓了该框架输入/输出的具体逻辑,理论上我们就可以熟练的使用任意框架!

当然作为一名有志于成为高级开发的开发者来说,仅仅知晓框架基础使用肯定是远远不够的。因为这样你的可替代性太大了,所以不断的深入分析框架的源码,剖析框架的运行原理成为了我们脱颖而出的一种手段。 可能你会想这些框架源码在工作中会用到吗?说句实话,其实工作中大多数时候是用不到的,用不到那读源码还有什么用呢?

在回答这一问题之前,我们不妨先来思考这样一个问题。那就是面对浩瀚的源码你是否知道该从何处入手?

面对这样一个问题,我想对于大部分刚入行的程序员来说其实很难给出准确答案的。或许,我们的印象中程序员只要会写代码就行了。但事实上真是如此吗?

事实上,对于一名程序员来说,不仅要会写代码更要擅长阅读他人的代码。因为作为程序员的我们不可能每次开发都贯穿产品的整个生命周期,而对于前人代码修修补补是我们工作中所必须面对的。此时如何读懂前人遗留就显得尤为重要,为此具备读懂代码的能力便显得格外重要。

正如我们之前所说的那样,所有的框架其实完全可以视为输入/输出的过程。换言之,一个框架将输入信息处理为输出结果过程就是该框架的核心逻辑,也即框架的主流程。所以只要分析清楚这条主流程,我们就能快速读懂框架背后的执行逻辑,然后在不断在此基础上深耕。

接下来,笔者便以常见的Mybatis为例来分析,看看我们在读源码时究竟该如何把握住主线。

Mybatis是什么?

看到这问题,我想你肯定会想到如下的话术

MyBatis是一个开源的Java持久化ORM框架,其通过XML或注解实现对象与数据库数据的映射,将SQL语句与Java代码分离,提供灵活的动态SQL和各种参数映射方式。其支持一级和二级缓存,同时其还拥有插件体系以及与Spring等框架集成的事务管理功能。其简单性和易学性使其成为开发者在Java应用程序中执行数据库操作时的首选框架。

我想对于大部分刚接触Mybatis开发者而言一定听过上述这样一段对于Mybatis的概述。不可否认的是,这样的描述确实准确的概括了Mybatis的特点。但其毕竟是标准的"应试"答案。进一步,其实该答案只是对Mybatis框架的一些特性进行介绍,并未触及到Mybatis的原理。

那究竟什么是Mybatis的核心逻辑呢?在回答这一问题之前,我们先来看这样一段代码:

public class JDBCDemo {
   
    // .... 省略驱动加载
    
    // 1. 建立数据库连接
   Connection connection = DriverManager.getConnection(url, username, password);
            
    // 2. 创建SQL语句
    Statement statement = connection.createStatement();
    
    // 3. 执行SQL查询
    String selectSql = "SELECT * FROM yourtable";
    ResultSet resultSet = statement.executeQuery(selectSql);

    //4. 处理查询结果
    while (resultSet.next()) {
        int id = resultSet.getInt("id");
        String name = resultSet.getString("name");
      // 处理封装数据
       }
    }
}

我想如果你Java基础扎实的话,看到上述代码相信你一定会脱口而出,这不就是原生JDBC操作数据库的逻辑吗?如果我继续追问,当Mybatis框架出现后,你还写过这样的代码吗?答案是肯定是否的。

更进一步,为什么Mybatis框架出现后我们不用再通过JDBC原生API来操纵数据库呢?答案其实很简单,因为Mybatis框架内部已经代替我们完成了这些操纵数据库的繁琐了。

至此,Mybatis的主干逻辑其实已经开始变得清晰了。对于Mybatis框架而言,其核心逻辑就是原生 JDBC操作SQL 执行过程。

剖析Mybatis核心逻辑

明确了Mybatis框架的核心主干就是JDBC后,我们再来看我们入门 Mybatis时的经典代码:

  //<1> 加载配置文件
  InputStream is = Resources.getResourceAsStream("mybatis.xml");
  //<2> 创建sessionFactory对象
  sessionFactory = new SqlSessionFactoryBuilder().build(is);
  //<3> 获取sqlSession对象信息
  SqlSession session = factoy.openSqlSession()
  //<4> 构建映射器的代理对象
  UserMapper mapper = session.getMapper(UserMapper.class);
  // .....调用相关方法信息

具体来说,上述代码主要做了如下几件事:

  • 通过工厂构造器构建一个SqlSessionFactory对象

  • 通过SqlSessionFactory获取到一个sqlSession对象

  • sqlSession中传入一个Mapper对象信息,同时获取到一个Mapper对象

  • 获取Mapper对象的代理类,调用接口中的方法,从而执行相关sql语句

显然,在上述代码中我们使用了Mybatis 为我们提供了两个核心对象,一个是 SqlSession,另一个是 Mapper

但在分析之前,我们首先要明确一件事那便是在Mybatis中构建SqlSession需要采用工厂模式通过 SqlSessionFactory 来构建。进一步,上述代码中会通过SqlSessionFactoryBuilderbuild方法构建一个一个 SqlSessionFactory

如果你在深究build方法其内部逻辑不过 Mybatis 内部对于配置文件的解析。


public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
   
      XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
      return build(parser.parse());
   
}

public Configuration parse() {
    ...
    parseConfiguration(parser.evalNode("/configuration"));
    return configuration;
}

其中详细的解析逻辑我们在此便不再赘述,而如下这张图便准确的反映了构建Mybatis内部解析配置文件时的全过程。

谈一谈初学者该如何快速入门Mybatis源码

当获取到SqlSessionFactory后,便可以通过该工厂类中的工厂方法来创建 SqlSession 对象。进一步,当获取到SqlSession对象后,我们便会构建接口对应的Mapper。更进一步,Mybatis内部获取Mapper的过程如下所示:

谈一谈初学者该如何快速入门Mybatis源码

在构建Mapper的过程中,我们首先会通过SqlSession中的getMapper方法来获取Dao接口的代理对象。而在Mybatis内部,其会将这部分逻辑委托为Configuration中的mapperRegistry 来完成。最终通过构建一个 MapperProxyFactory的形式来构建Dao接口所对应的代理类。

事实上,由于这部分代码逻辑比较复杂, 在初次学习Mybatis源码时对这部分内容完全可以将这部选择性"忽视“,只需知道Mybatis内部最终会通过代理的形式构建一个Dao接口所对应的代理Mapper类即可!

Mapper通过代理形式生成后,其在执行内部方法时又会回到 SqlSession内部,并委托Mybatis内部一个执行器Executor 组件进行执行。别看其名字起的高大上,其实做的工作不过是JDBC那一套工作罢了!

总结

经过我们这样一分析,你觉得Mybatis还难吗?是不是觉得其本身就是JDBC执行Sql语句的那一套逻辑笔者相信只要顺着这样的思路去分析Mybatis源码你一定可以快速上手Mybatis源码内容,同时当你养成这样分析框架主干的逻辑后,你会发现,日后再去分析类型Spring、SpringMVC等优秀框架时会变的非常轻松!

最后,希望文章对你学习源码有所帮助!当然如果觉得有所收获,不妨点赞+收藏+关注作者!笔者也将持续分享自己在Debug框架源码时的一些所见所想,希望这些内容能真正帮助到你~