前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >阿里的御用框架,MyBatis与设计模式的激情碰撞

阿里的御用框架,MyBatis与设计模式的激情碰撞

原创
作者头像
程序员白楠楠
修改2020-12-23 11:35:53
3010
修改2020-12-23 11:35:53
举报

前言

Java程序员以前连接数据库是这样的

现在连接数据库是这样的

在传统的JDBC 实现中,我们需要把查询过程写在Java 类中,这样非常不便于后期维护。而使用Mybatis 则可以将查询语句配置在配置文件中,只需要维护好映射关系即可。

Mybatis是一个开源的轻量级半自动化ORM框架,使得面向对象应用程序与关系数据库的映射变得更加容易。熟悉Mybatis的都知道,其源码里涉及到非常多的设计模式,比如

设计模式

Builder模式:例如SqlSessionFactoryBuilder、XMLConfigBuilder、XMLMapperBuilder、XMLStatementBuilder、CacheBuilder;

工厂模式:例如SqlSessionFactory、ObjectFactory、MapperProxyFactory;

单例模式:例如ErrorContext和LogFactory;

代理模式:Mybatis实现的核心,比如MapperProxy、ConnectionLogger,用的jdk的动态代理;还有executor.loader 包 使用了cglib或者javassist达到延迟加载的效果;

组合模式:例如SqlNode和各个子类ChooseSqlNode等;

模板方法模式:例如BaseExecutor和SimpleExecutor,还有BaseTypeHandler和所有的子类例如IntegerTypeHandler;

适配器模式:例如Log的Mybatis接口和它对jdbc、log4j等各种日志框架的适配实现;

装饰者模式:例如Cache包中的cache.decorators子包中等各个装饰者的实现;

迭代器模式:例如迭代器模式PropertyTokenizer;

关注公众号“程序员白楠楠”获取一份562页的设计模式资料

如果之前只会使用或者没有看过Mybatis源码,那看到上面这些设计模式可能会有点懵逼。Mybatis用了这么多年了,只会用它来CRUD数据库吗?其底层的架构设计与源码分析,如何连接数据库的?如何执行的?一二级缓存的作用?sql如何解析的?源码中设计到的设计模式......这些技术点都会吗?

Mybatis源码分析

今天,我们就来看看Mybatis源码的阅读,具体举个例子来看看:

案例和疑问

从我们最初的demo中开始:

代码语言:javascript
复制
public static void main(String[] args) {
        String resource = "mybatis-config.xml";
        InputStream inputStream = null;
        SqlSession sqlSession = null;
        try {
            inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            sqlSession = sqlSessionFactory.openSession(); 
            User user = sqlSession.selectOne("com.tian.mybatis.mapper.UserMapper.selectById", 1);
            System.out.println(user); 
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            sqlSession.close();
        }
    }

关于获取数据流inputStream,这个我们就不讨论了,我们主要关注重点。

对于上面demo,我们可以分成五个步骤:

第一步,创建一个工厂类sqlSessionFactory。

配置文件的解析就是在这里完成的。包括mybatis-config.xml和我们的Mapper.xml映射器文件。这一步我们关心的内容是:解析的时候做了什么?产生了什么对象,解析的结果放在哪里的。因为这将意味着,我们后面使用的时候去哪里获取这项配置项内容。

第二步,通过SqlSessionFactory创建一个SqlSession。

那么问题来了,SqlSession中定义了各种增删改查的API,是给客户端调用,返回的是什么实现类?除了SqlSession以外,我们还创建了什么对象,创建了什么环境?

第三步,获取到一个Mapper对象。

问题来了UserMapper.java是一个接口,并没有为它创建实现类,那又是怎么被实例化的呢?我们使用的这个Mapper对象到底是什么对象呢?为什么要从SqlSession里去获取呢?为什么传进去一个接口,然后还要用一个接口去接收呢?

第四步,调用接口方法。

问题是我们的接口没有实现类,为什么就可以直接调用它的方法呢?那它调用的是谁的方法呢?是如何把SQL给关联起来的呢?是如何获取到数据的呢?

第五步,关闭相关资源。

开始源码分析过程

由于涉及到内容较多,下面就用几张图来展示整个流程。我们可以通过这几张图来快速翻阅Mybatis的源码。

第一步

代码语言:javascript
复制
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

这一句代码的整个流程如下:

根据inputStream,解析配置文件,创建出一个DefaultSqlSessionFactory默认的SqlSessionFactory 实现类。构建出一个工厂类,这个工厂类专门用来创建SqlSession对象的。

第二步

代码语言:javascript
复制
SqlSession  sqlSession = sqlSessionFactory.openSession();

获取SqlSession的整个流程如下:

第三步

代码语言:javascript
复制
User user = sqlSession.selectOne("com.tian.mybatis.mapper.UserMapper.selectById", 1);

第三步和第四步就是这行代码画的。

这一步是返回一个映射器代理类,映射器代理类专门用来给UserMapper接口和UserMapper.xml绑定的代理类。创建出来的代理类就可以实例化了,然后就可以调用UserMapper接口的方了。

第四步:调用代理对象执行SQL的整个过程。

第五步,关闭资源。

希望大家按照这个流程,找点源码看看。听别人的看别人永远是别人的。

动起来吧!

个人建议

对于一般java程序员来说,阅读源码之前到底需要些什么技能呢?

个人建议,以下基础知识必须会一些:

会设计模式:包括单例模式、工厂模式、代理模式、装饰器模式、责任链模式、模板方法模式等。

会猜测:大胆的猜测,在看源码的时候,多站在高层次想想,如果你是Mybatis的设计者,你会怎么设计?

总结

Mybatis应该是国内用得最多的「数据访问层」框架了,看了我司的好几个系统,基本都是用Mybatis。所以深入了解Mybatis的重要性不言而喻。

小编总结一份562页的设计模式资料, 这份资料非常全面且详细,覆盖了 设计模式 基础学习的方方面面,非常适合初学者入门!

资料获取方式:关注公众号“程序员白楠楠”获取上述资料!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 设计模式
  • Mybatis源码分析
  • 案例和疑问
    • 第一步,创建一个工厂类sqlSessionFactory。
      • 第二步,通过SqlSessionFactory创建一个SqlSession。
        • 第三步,获取到一个Mapper对象。
        • 开始源码分析过程
          • 第一步
            • 第二步
              • 第三步
                • 第四步:调用代理对象执行SQL的整个过程。
                  • 第五步,关闭资源。
                  • 个人建议
                  • 总结
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档